6

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

带有 -std=c++0x 的环境gcc 版本 4.6.3 (Debian 4.6.3-14+rpi1)

  • 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 ‘&lt;brace-enclosed initializer list>’ make: *** [src/dummy.o] Error 1
  • 根据书籍,Code1 应该没问题。第 7.7.2 节,因为 var 是左值,但为什么 code1 不起作用但 code3 在我的情况下起作用?
4

1 回答 1

3

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

8.5.4 列表初始化

[#3]

-- 否则,如果 T 是引用类型,则 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.

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

int x;
int &y { x };

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

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

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

于 2013-10-12T07:36:46.293 回答