【问题标题】:lvalue initialization fails左值初始化失败
【发布时间】:2013-10-20 07:44:59
【问题描述】:

“The C++ Programming Language 4th Edition”中的一些示例代码让我感到困惑。这是我的测试用例。

Env gcc 版本 4.6.3 (Debian 4.6.3-14+rpi1) 与 -std=c++0x

  • Code1 string var {"Cambridge"}; string& r1 {var}; 编译失败
  • Code2 string var {"Cambridge"}; string& r1 = var; 编译成功
  • Code3 string var {"Cambridge"}; string&& r1 {var}; 编译成功
  • Code1 编译失败 g++ -g -DLINUX -std=c++0x -c src/dummy.cpp -o src/dummy.o src/dummy.cpp: In function ‘int main(int, char**)’: src/dummy.cpp:26:17: error: invalid initialization of non-const reference of type ‘std::string& {aka std::basic_string<char>&}’ from an rvalue of type ‘<brace-enclosed initializer list>’ make: *** [src/dummy.o] Error 1
  • Code1 应该没问题。第 7.7.2 节,因为 var 是左值,但为什么 code1 不起作用但 code3 在我的情况下起作用?

【问题讨论】:

  • 看起来像是 GCC(包括 4.8)中的一个错误,Clang 接受版本 1 就好了。
  • 您遇到了DR1288。希望最近的编译器会实施建议的解决方案,而不是标准化缺陷。

标签: c++ string gcc c++11


【解决方案1】:

它失败了,因为它试图将一个右值绑定到一个非常量左值引用。

8.5.4 列表初始化

[#3]

-- 否则,如果 T 是引用类型,则该类型的 prvalue 临时 被 T 引用的是列表初始化的,而 引用是 绑定到那个临时的。 [注意:和往常一样,绑定会失败 如果引用类型是对非常量类型的左值引用,则程序格式错误。 ——尾注]

检查此示例以验证 r1 是否绑定到不同的对象

#include <string>
#include <iostream>

int
main () {
  std::string var {"Cambridge"};
  const std::string& r1 {var}; 
  const std::string& r2 (var);

  var.clear ();

  std::cout << "var = " << var << std::endl;
  std::cout << "r1 = " << r1 << std::endl;
  std::cout << "r2 = " << r2 << std::endl;
}

并将其与r2 进行对比。

附言。现在问题来了,根据上述考虑,为什么以下操作不会失败:

int x;
int &y { x };

标准说(在与上面相同的地方,但下一个条款):

-- 否则,如果初始化列表只有一个元素,则从该元素初始化对象或引用

该子句明确提到了引用,换句话说,初始化引用并没有在单个子句中描述,但是有几种可能性(可能按子句的顺序尝试?),这就解释了为什么int &amp; 会这样.

【讨论】:

  • 感谢您的回复。那么这是否意味着这本书的代码是错误的?它试图说这是一个正确的演示代码string&amp; r1{var}; //lvalue reference, bind r1 to var(an lvalue)本书的第7.7.2节
  • 能否请您提供一些有关您的编译器的信息?您是否在编译示例代码时遇到了相同的“编译错误”?
  • 此处使用 GCC 4.8.1。是的,我认为这本书有误,那里还有另一本书string&amp;&amp; rr2 {var}; 应该可以工作。
  • 我还没收到。如果在 code1 中将“string”替换为“int”,那么它可以工作。按照这个逻辑,我们会得出结论“var is lvalue(int var {1}” and var is rvalue(string var {"abcd"}.
  • 不同类型的语言规则不同,e.g. int 不是类类型。恐怕你需要检查 C++ 标准,第 8.5.4 节 [#3],在这里复制有点太长了,但你可以在这里阅读下一个标准的草案,isocpp.org/files/papers/N3690.pdf,它是相同的。但是,确实,我必须与int &amp; 核对。等等……
猜你喜欢
  • 1970-01-01
  • 2016-03-25
  • 2012-11-17
  • 2017-12-10
  • 2018-09-17
  • 1970-01-01
  • 2018-10-13
  • 2014-03-13
  • 1970-01-01
相关资源
最近更新 更多