C++ 当我传递对这个函数的引用时,为什么它不工作?
代码如下:C++ 当我传递对这个函数的引用时,为什么它不工作?,c++,reference,C++,Reference,代码如下: void test(string &s){ // if the argument is "string s", it works return test(s+','); } 编译器报告找不到函数:test(std::basic_string) 我想编译器会创建一个临时字符串(=s+,),我可以传递它的引用。 但似乎我错了。我不知道为什么我不能传递此临时字符串的引用。使其成为常量: void test(const std::string &s){ // if
void test(string &s){ // if the argument is "string s", it works
return test(s+',');
}
编译器报告找不到函数:test(std::basic_string)
我想编译器会创建一个临时字符串(=s+,),我可以传递它的引用。
但似乎我错了。我不知道为什么我不能传递此临时字符串的引用。使其成为常量:
void test(const std::string &s){ // if the argument is "string s", it works
return test(s+',');
}
标准C++不允许非const LValk引用绑定到一个rValk。在您的示例中,“
s+”,“
表达式的结果是一个临时的,因此是一个右值,因此编译器需要丢弃test
的重载,该重载应为左值引用,而不允许调用它。这就是为什么它抱怨无法找到函数test
要解决此问题,必须提供一个重载,其参数可能绑定到右值。正如您自己所意识到的,通过copy期望参数是可行的,但通过调用copy/move-ctors可能意味着不必要的开销。更好的选择是通过引用期望参数。由于常量左值引用可能绑定到右值,因此按如下方式声明函数可以解决问题
void test(std::string const& s)
不能将临时引用绑定到非常量引用。您可以通过
const
reference(或者,正如您所指出的,通过值)获取参数
或者使用命名变量而不是临时变量
void test(string & s){
std::string s2 = s + ',';
return test(s2);
}
如前所述,在注释中,该代码具有未定义的运行时行为,不应在“真实”代码中使用;它的目的只是一个如何修复观察到的编译错误的最小示例,但首先您应该看到这个问题字符串连接 替代解决方案
void test(string &s)
{
s.append(",");
return test(s);
}
您正在尝试将临时引用绑定到非常量引用。这在标准C++中是不允许的。答案将取决于你想要实现什么。可能不是堆栈溢出。只是一个旁白-您是否知道您的示例(一旦更正)将导致无限递归?这会导致堆栈溢出。为什么我需要将其设为常量?如果我想更改s的内容,该怎么办?这是不可能的。您将更改临时对象的内容,这是不允许的。要修改它,请将此参数更改为std::string s,没有引用“但它自然意味着不必要的开销”——这里不会使用move-ctor吗?@marcin_j在这种特殊情况下,假设编译器至少实现了C++11标准,并且没有完成复制/移动省略,我相信它会。然而,一个move-ctor本身的开销比没有任何ctor都要大,这是通过将引用作为函数参数来实现的。因此,即使它可能不是,也可能意味着不必要的开销。我将修改这句话,以明确这是一种可能性而不是确定性。当然,这仍然是错误的,因为
test
没有返回任何内容。@LightnessRacesinOrbit:确实如此,但问题只是“这为什么不编译?”,没有必要通过使最小测试用例正确递归而使其复杂化。那么,由于它仍然无法编译,您最多只能回答一半的问题。@LightnessRacesinOrbit:您的意思是什么,无法编译?它编译得很好:。显然它不会正确运行,因为递归永远不会结束,但这超出了问题的范围。@LightnessRacesinOrbit:哦,是的,我没有发现我从问题中复制的void
;出于某种原因,我的编译器也没有。也许你本可以指出这一点,而不是在这件事上胡说八道。不管怎样,现在已经修好了。
void test(string &s)
{
s.append(",");
return test(s);
}