Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/156.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 当我传递对这个函数的引用时,为什么它不工作?_C++_Reference - Fatal编程技术网

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