3
votes

This is the code from c++ primer:

string::size_type findChar(const string &s, char c, string::size_type & occurs){
    auto ret = s.size();
    occurs = 0;
    for (decltype(ret) i = 0; i != s.size(); ++i){
        if (s[i] == c){
            if (ret == s.size())
                ret = i;
            occurs++;
        }
    }
    return ret;
}

int main () {
    string::size_type ctr;
    cout << findChar("hello, world!", 'o', ctr);
}

An error happened after removing const from const string &s.

error: cannot bind non-const lvalue reference of type 'std::__cxx11::string&' {aka 'std::__cxx11::basic_string&'} to an rvalue of type 'std::__cxx11::string' {aka 'std::__cxx11::basic_string'} cout << findChar("hello, world!", 'o', ctr);

I wonder, in this case, what behaviors of compiler does the const keyword change? Thanks for helping me.

3
What error, exactly, happened?Nathan Pierson
Removing const means "this value can be manipulated" which may not be permitted depending on how the argument is provided.tadman
@nathanpierson I have added it into the question.Swa1n Suen
You need to study c++ move semanticsHarry

3 Answers

7
votes

A string literal like "hello, world!" is not a std::string. So to call your function the compiler has to create a std::string for you. Such an object is called a temporary. So in the first case the compiler uses "hello, world!" to create a std::string and then binds that temporary string to reference parameter s.

However C++ has a rule that you cannot bind a temporary to a non-const reference. But when you change s from const std::string& to std::string& you are asking the compiler to do exactly that. This is what the error message is telling you.

If you changed your code to this

string::size_type ctr;
string hello = "hello, world!";
cout << findChar(hello, 'o', ctr);

it will now compile even without const. The difference here is that the compiler is no longer creating a temporary std::string (because hello is already a std::string). So the rule about temporaries and non-const references doesn't apply.

0
votes

std::string is a class. const char* is a pointer to memory that hopefully contains a null-terminated string. You can use std::string to pass by value and make copies without having to call functions like strcpy.

Use std::string whenever you can and the c_str() method when you need a pointer to the string, e.g., for older C libraries.

0
votes

In the calling code, the object passed for s is "hello, world!", which is a string whose contents that cannot be changed. In the function findChar the type const string &s is a reference named s to an object of type const string. These two types are matched, so the compilation completes successfully.

However, a parameter string &s denotes a referenced named s to an object of type string - this is a mutable (changeable) string. But the passed in argument ("hello, world!") is a string that cannot be changed. When this happens the compiler indicates a type mismatch error.