0

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?

2
  • Why pass a whole string to is_vowel when you could pass a single character? Perhaps it was just for an example? Commented Apr 15, 2014 at 20:46
  • I did intend to use char instead of string, if that's what you mean. I just use string for a little bit of consistency. Commented Apr 15, 2014 at 20:56

1 Answer 1

3

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.

Sign up to request clarification or add additional context in comments.

3 Comments

I see. So based on your explanation, is it correct that the main function works even when the FRI_Syllables function is not const because words[i] is a lvalue (not "temporary") so it can bind with a non-const lvalue?
Just as a C++ beginner myself, one of my "aha" moments came the other day when I realized that "lvalue" and "rvalue" (probably) refer to the left- and right-hand sides of an assignment expression. Lvalues can be assigned to; rvalues can't. Might've been obvious but the texts I read never made that explicit and it took me a while to make the connection.
@dmau1982: Yes, that's the origin of the name, though it's more of a mnemonic now than an actual, precise term. By the way, in C there are only "lvalues" and things that are "not an lvalue". The term "rvalue" (and "xvalue") seems to have been invented for C++.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.