JupiterM
JupiterM

Reputation: 47

Reference parameter (&) with and without const in C++

So I was writing a program yesterday, and I encountered a problem that when I use a reference without const, it'll be an error whenever I tried to call that function later. For example:

bool is_vowel(const string& s) //OK;
bool is_vowel(string& s) //Error!
{
    if (s == "A" || s == "a") return true;
    if (s == "E" || s == "e") return true;
    if (s == "I" || s == "i") return true;
    if (s == "O" || s == "o") return true;
    if (s == "U" || s == "u") return true;
    if (s == "Y" || s == "y") return true;

    return false;
}

And considering the following that calls this function: (for simplicity, I've cut out a huge chunk of the original code, so don't focus on the logic here)

int FRI_Syllables(const string& s)
{
    int syllables = 0;

    for (int n = 0; n < s.length(); n++)
        if (is_vowel(s.substr(n, 1)))
            syllables ++;
}

return syllables;

}

So when I use this function, the line that calls is_vowel when I don't use const will return a compile-time error saying "No matching function for call to 'is_vowel'".

I know why references with const here works; what I don't understand is why the one without doesn't.

And another thing that makes me more confusing is that in the FRI_Syllables function, the references work with AND without the const. So considering a part of the code in the main function that calls this function:

int main()
{
    //rest of the code

    int syllables = 0;
    for (int i = 0; i < words.size(); i++)
        syllables += FRI_Syllables(words[i]);

    //rest of the code
}

This won't return any error whether I use int FRI_Syllables(const string& s) or int FRI_Syllables(string& s). So why the differences? Why would references without const sometimes work and others don't?

Upvotes: 0

Views: 88

Answers (1)

Kerrek SB
Kerrek SB

Reputation: 477010

A non-const lvalue reference variable only binds to lvalues, not to rvalues. By contrast, a const lvalue reference binds to both lvalues and rvalues.

Since the result of s.substr(n, 1) is an rvalue (a "temporary value"), it cannot bind to a non-constant lvalue reference.

The reasoning behind this language design choice is that the purpose of a non-constant lvalue reference is to allow you to change the object that's being referred to, but when that object is temporary, the changes would be lost immediately, so this is basically never what you could have intended.

Upvotes: 3

Related Questions