错误:无法将类型为“int&”的非const左值引用绑定到类型为“int”的rvalue

22

我需要创建一个Bar对象,其中有一个私有对象Foo f

然而,Foo对象参数的值应该由特定方法int genValue()传递。

如果我在构造函数作用域Bar(){...}中初始化f,编译器会报错,类似于没有构造函数Foo()

如果我这样构造Bar(): f(genValue()),编译器会报错:

test.cpp: In constructor ‘Bar::Bar()’:
test.cpp:16:19: error: cannot bind non-const lvalue reference of type ‘int&’ to an rvalue of type ‘intBar(): f(genValue()){    
            ~~~~~~~~^~
test.cpp:7:2: note:   initializing argument 1 of ‘Foo::Foo(int&)’    
 Foo(int &x) {    
 ^~~

示例代码:

class Foo {
public:
    Foo(int &x) {
        this->x = x;
    }
private:
    int x;
};

class Bar {
public:
    Bar(): f(genValue()){
    }
private:
    Foo f;

    int genValue(){
        int x;
        // do something ...
        x = 1;
        return x;
    }
};

int main() {

    Bar bar ();

    return 0;
}

如果我不想修改Foo类,并且其参数值应该从genValue()传递,我该如何解决问题?同时,我不想使用纯指针(*),但使用智能指针的解决方案可以!


如果最终你要复制,那么让 Foo 接受一个引用就没有意义了。只需将 Foo 的构造函数更改为 Foo(int x) : x(x) { } 即可。 - Jans
2个回答

20

const引用参数,比如int&,只能引用“左值”,也就是一个有名字的变量。

auto takes_nonconst_reference = [](int&){};
auto takes_const_reference = [](const int&){};
auto takes_value = [](int){};
auto returns_int = []{return 42;};

int foo = 1;

// OK
takes_nonconst_reference(foo);
takes_const_reference(foo);
takes_const_reference(returns_int());
takes_value(foo);
takes_value(returns_int());

// compilation error, value returned from a function is not a named variable
takes_nonconst_reference(returns_int());

在这种情况下,由于您的类存储构造函数参数的副本,所以应该通过值传递它(int而不是int&const int&)。


1
命名变量可能是左值,但并非所有左值都是命名变量。这些也是左值:v.at(5)*this*(p + 42) - Ben Voigt
1
@BenVoigt 我故意过于简化,因为OP似乎是初学者。 - Ray Hamel
过度简化是导致原帖作者陷入麻烦的原因。 - Ben Voigt
3
深入探讨各种值类别的细节对于初学者并没有什么帮助,只会导致混淆和气馁。在“lvalues是命名变量,rvalues是临时变量”这个启发式规则下,足以为初学者提供足够好的指引,而且并不比英语中的“I before E except after C”这句简化规则更过分。 - Ray Hamel
2
此外,如果我们要严谨一些,某些lvalue没有存储位置,例如非类型模板参数和[[no_unique_address]]空数据成员。 - Ray Hamel
显示剩余3条评论

13

不要传递 int&,因为它无法绑定到常量或临时变量,因为这些无法修改-请使用const int& 代替。

实际上,对于简单类型,您应该更倾向于通过值传递,并让优化器担心提供最佳实现。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接