3

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.

Swa1n Suen
  • 129
  • 1
  • 6

3 Answers3

7

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.

john
  • 85,011
  • 4
  • 57
  • 81
0

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

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.

Phillip Ngan
  • 15,482
  • 8
  • 63
  • 79
  • This is untrue. The type mismatch causes the compiler to construct a temporary, and it the rule about binding non-const references to temporaries that causes the compiler error, not the type mismatch. – john Dec 13 '20 at 08:33