const string &s 和 string &s 有什么区别?

What is the difference between const string &s and string &s?

这是来自 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);
}

const string &s 中删除 const 后发生错误。

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);

我想知道,在这种情况下,const 关键字会改变编译器的哪些行为?谢谢你帮助我。

std::string 是一个 class。 const char* 是指向内存的指针,希望包含以空字符结尾的字符串。您可以使用 std::string 按值传递并进行复制,而无需调用 strcpy 等函数。

尽可能使用 std::string,当需要指向字符串的指针时使用 c_str() 方法,例如,对于较旧的 C 库。

"hello, world!" 这样的字符串文字不是 std::string。所以要调用你的函数,编译器必须为你创建一个 std::string 。这样的对象称为临时。因此,在第一种情况下,编译器使用 "hello, world!" 创建一个 std::string,然后 绑定 该临时字符串以引用参数 s.

但是 C++ 有一条规则,您不能将临时对象绑定到非常量引用。但是,当您将 sconst std::string& 更改为 std::string& 时,您是在要求编译器执行此操作。这就是错误消息告诉您的内容。

如果您将代码更改为此

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

现在即使没有 const 也能编译。这里的区别是编译器不再创建临时 std::string(因为 hello 已经是 std::string)。因此关于临时引用和非常量引用的规则不适用。

在调用代码中,s传递的对象是"hello, world!",是一个字符串,其内容不可更改。在函数 findChar 中,类型 const string &s 是对类型 const string 对象的名为 s 的引用。这两个类型匹配,所以编译成功。

但是,参数 string &s 表示对 string 类型对象的命名 s 的引用 - 这是一个可变(可变)字符串。但是传入的参数("hello, world!")是一个不能改变的字符串。发生这种情况时,编译器会指示类型不匹配错误。