【问题标题】:Error: cannot bind non-const lvalue reference of type ‘int&’ to an rvalue of type ‘int’错误:无法将“int&”类型的非常量左值引用绑定到“int”类型的右值
【发布时间】:2021-07-19 16:26:16
【问题描述】:

我需要创建一个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 ‘int’
 Bar(): 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) { }

标签: c++ class constructor


【解决方案1】:

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&)。

【讨论】:

  • 命名变量可能是左值,但并非所有左值都是命名变量。这些也是左值:v.at(5)*this*(p + 42)
  • @BenVoigt 我故意过分简化,因为 OP 似乎是初学者。
  • 过度简化是 OP 陷入困境的原因
  • 深入了解各种价值类别的所有细节对初学者完全没有帮助,只会让人感到困惑和沮丧。 “左值是命名变量,右值是临时变量”对于初学者来说是一个足够好的启发式方法,并且对于英语来说,“I before E before C except after C”没有更多的“过度简化”。
  • 另外,如果我们是迂腐的,某些左值没有存储位置,例如非类型模板参数和[[no_unique_address]] 空数据成员。
【解决方案2】:

不要传递int&,它不能绑定到常量或临时,因为它们不能被修改 - 请改用const int&

实际上,对于简单类型,您应该更喜欢按值传递,而让优化器担心提供最佳实现。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-11-07
    • 2021-03-03
    • 1970-01-01
    • 2012-01-07
    • 2021-10-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多