【问题标题】:Error in invalid initialization of non-const reference of type类型的非常量引用的无效初始化错误
【发布时间】:2013-10-11 00:08:45
【问题描述】:

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

错误信息:

从“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;
}

【问题讨论】:

  • 您不能将临时对象绑定到非常量引用。它应该改变什么?
  • 当然是临时的。我从来没有真正同意这条规则,但我曾经收到 Bjarne Stroustrup 本人的回复,他说他觉得允许代码像这样修改临时变量“太混乱”。

标签: c++


【解决方案1】:

一个简单的解释是,由于你的 replaceAll 函数正在改变一个字符串,你必须给它一个实际的字符串才能改变。

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

【讨论】:

  • 我觉得你的“简化解释”很简单!
【解决方案2】:

这应该可以消除错误:

#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;
}

【讨论】:

  • 这是正确的。然而,真正的问题是为什么原始代码是一个错误,而不是完全按照它做的。这段代码所做的是用户所期望的(如果 replaceAll 返回一些其他信息,例如替换了多少个,则更明显,因此代码想要忽略修改后的字符串是有道理的)。
【解决方案3】:

如果您希望能够将临时变量作为参数传入,则可以改为返回结果:

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

【讨论】:

    【解决方案4】:

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

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

    正如@Umer 和@john 所写的

    【讨论】:

    • 这是一个有点误导性的解释。问题不在于双引号中的字符串是常量,问题实际上在于双引号中的字符串不是std::string类型,所以编译器必须构造一个temporary std::string为了调用该函数,C++ 中的规则是您不能将非常量引用绑定到临时对象。相同的规则将停止此代码编译 string function_returning_a_string(); ... replaceAll(function_returning_a_string(), "n", "k");,即使在这种情况下不涉及 const。
    • Thnx @john fr 详细说明:)
    • 不幸的是临时的不是固定的。例如,此代码是合法的string function_returning_a_string(); ... function_returning_a_string() = "abc";。规则是您不能将非常量引用绑定到临时对象,无论临时对象是否为常量都无关紧要。如果你删除 '(这是一个常量)' 就可以了。
    猜你喜欢
    • 2013-09-04
    • 2015-01-26
    • 1970-01-01
    • 2023-04-04
    • 2013-01-07
    • 2012-01-07
    • 2021-10-26
    • 1970-01-01
    相关资源
    最近更新 更多