【问题标题】:Lvalue decaying to rvalue with auto error左值衰减为右值并出现自动错误
【发布时间】:2014-12-15 19:46:50
【问题描述】:

如果问题标题不准确,我深表歉意 - 但我很难理解这里发生了什么。

考虑以下类:

struct foo {
    foo(foo&);
};

以下没有错误:

void func(foo& f) {
    foo bar{f};
}

但是,当我使用自动时:

void func(foo& f) {
    auto bar = foo{f};
}

我得到(gcc):

test.cpp: In function ‘void func(foo&)’:
test.cpp:6:21: error: no matching function for call to ‘foo::foo(foo)’
test.cpp:6:21: note: candidate is:
test.cpp:2:5: note: foo::foo(foo&)
test.cpp:2:5: note:   no known conversion for argument 1 from ‘foo’ to ‘foo&’

(叮当声)

test.cpp:6:10: error: no matching constructor for initialization of 'bar'
    auto bar = foo{f};
         ^     ~~~~~~
test.cpp:2:5: note: candidate constructor not viable: expects an l-value for 1st argument
    foo(foo&);
    ^

有人可以解释为什么这是一个错误吗?

谢谢!

编辑:如果我将复制构造函数添加到 foo.但是,我的印象是,'=' 语法右侧的变量声明 + 对构造函数的显式调用被特殊处理,不是复制构造,而是直接初始化。

【问题讨论】:

    标签: c++ c++11 auto lvalue


    【解决方案1】:
    auto bar = foo{f};
    

    auto 推导出为foo。随后,您的定义相当于

    foo bar = foo{f};
    

    您正在尝试创建使用纯右值 foo{f} 进行复制初始化的 foo 类型的对象。

    问题是foo的复制构造函数有一个非常量左值引用作为它的参数,这是不可能绑定到右值的。此外,移动构造函数不是隐式定义的,因为您有一个用户声明的复制构造函数。因此没有可以接受foo{f}的构造函数,编译器会发出错误消息。

    【讨论】:

    • 编译器会调用复制构造函数吗?我的印象是编译器会将其视为直接初始化。
    • 啊在android上打字很慢,好像也没有办法删除答案
    • @RobertMason 编译器可能会忽略对没有副作用的复制构造函数的调用,但复制构造函数必须仍然是可调用的。
    • @RobertMason 不管调用是否会被省略,构造函数必须是可调用的并且产生一个有效的调用。
    【解决方案2】:
    auto bar = foo{f};
    

    这是复制初始化,根据其语义,它需要复制构造函数的存在。但是foo的复制构造函数采用非常量引用,非常量引用不能绑定到临时的,即foo{f}

    解决方案是创建一个接受 const 引用的复制构造函数,就像复制构造函数通常做的那样。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-01-20
      • 1970-01-01
      • 1970-01-01
      • 2019-07-05
      • 1970-01-01
      • 1970-01-01
      • 2019-04-28
      相关资源
      最近更新 更多