C++ 类型的非常量引用初始化无效时出错

C++ 类型的非常量引用初始化无效时出错,c++,C++,下面是从字符串中查找和替换子字符串的代码。但我无法将参数传递给函数 错误消息: 从“const char*”类型的右值初始化类型为“std::string&{aka std::basic_string&}”的非常量引用无效 请帮忙解释一下 #include <iostream> #include <string> using namespace std; void replaceAll( string &s, const string &search,

下面是从字符串中查找和替换子字符串的代码。但我无法将参数传递给函数

错误消息:

从“const char*”类型的右值初始化类型为“std::string&{aka std::basic_string&}”的非常量引用无效

请帮忙解释一下

#include <iostream>
#include <string>
using namespace std;

void replaceAll( string &s, const string &search, const string &replace ) {
    for( size_t pos = 0; ; pos += replace.length() ) {
        pos = s.find( search, pos );
        if( pos == string::npos ) break;
        s.erase( pos, search.length() );
        s.insert( pos, replace );
    }
}
int main() {

    replaceAll("hellounny","n","k");
    return 0;
}
#包括
#包括
使用名称空间std;
void replaceAll(字符串和序列、常量字符串和搜索、常量字符串和替换){
对于(size_t pos=0;pos+=replace.length()){
pos=s.find(搜索,pos);
如果(pos==string::npos)中断;
s、 擦除(pos,search.length());
s、 插入(位置,更换);
}
}
int main(){
替换所有(“hellounny”、“n”、“k”);
返回0;
}

一个简化的解释是,由于replaceAll函数正在更改字符串,因此必须为其指定一个要更改的实际字符串

int main() {
    string str = "hellounny";
    replaceAll(str,"n","k");
    return 0;
}

这将删除以下错误:

#include <iostream>
#include <string>
using namespace std;

void replaceAll( string &s, const string &search, const string &replace ) {
    for( size_t pos = 0; ; pos += replace.length() ) {
        pos = s.find( search, pos );
        if( pos == string::npos ) break;
        s.erase( pos, search.length() );
        s.insert( pos, replace );
    }
}
int main() {

    string temp = "hellounny";
    replaceAll(temp,"n","k");
    return 0;
}
#包括
#包括
使用名称空间std;
void replaceAll(字符串和序列、常量字符串和搜索、常量字符串和替换){
对于(size_t pos=0;pos+=replace.length()){
pos=s.find(搜索,pos);
如果(pos==string::npos)中断;
s、 擦除(pos,search.length());
s、 插入(位置,更换);
}
}
int main(){
字符串temp=“hellounny”;
替换所有(温度,“n”、“k”);
返回0;
}

如果希望能够将临时值作为参数传入,可以返回结果:

std::string replaceAll(string s, const string &search, const string &replace ) {
    for( size_t pos = 0; ; pos += replace.length() ) {
        pos = result.find( search, pos );
        if( pos == string::npos ) break;
        result.erase( pos, search.length() );
        s.insert( pos, replace );
    }
    return s;
}

std::string result = replaceAll("hellounny", "n", "k");

代码的问题是,您试图使用非常量引用引用临时对象。编译器为表达式求值创建临时对象,以临时存储对象值(用于参数传递、从func返回值等)。您可以将非常量对象的地址分配给常量指针,因为您只是承诺不更改可以更改的内容。 但不能将常量对象的地址分配给非常量引用,因为这将允许您稍后修改该对象。 正确的方法是使用temp变量传递参数

int main()
{
    string temp = "This is a Temperory Var";
    replaceAll(temp,"n","k");
}

正如@Umer和@john所写的,您不能将临时引用绑定到非常量引用。它应该改变什么?当然是暂时的。我从来没有真正同意过这条规则,但有一次我收到了比亚恩·斯特劳斯塔普本人的回复,他说他觉得允许代码这样修改临时变量“太令人困惑了”。这是一个有点误导的解释。问题不是双引号中的字符串是常数,问题是双引号中的字符串不是STD::string类型,所以编译器必须构造一个临时STD::string来调用函数,而C++中的规则是不能绑定非const引用到一个临时的。相同的规则将停止此代码编译
string函数_返回_a_string()。。。replaceAll(函数返回字符串(),“n”,“k”)即使在本例中不涉及常量。Thnx@john fr detaining:)不幸的是,临时变量不是常量。例如,此代码是合法的
string函数_返回_a_string()。。。函数返回字符串()=“abc”。规则是不能将非常量引用绑定到临时引用,无论临时引用是否为常量都是无关的。如果你删除了“(这是一个常数)”,那么就没关系了。这是正确的。然而,真正的问题是,为什么原始代码是一个错误,而不是像这样做。这段代码所做的正是用户所期望的(如果replaceAll返回一些其他信息,例如有多少被替换,这将更加明显,因此代码希望忽略修改后的字符串是有意义的)。我发现您的“简化解释”非常简单!