当我使用g++编译下面的代码

class A {};

void foo(A&) {}

int main()
{
  foo(A());
  return 0;
}

我得到以下的错误消息:

> g++ test.cpp -o test     
test.cpp: In function ‘int main()’:
test.cpp:10: error: invalid initialization of non-const reference of type ‘A&’ from a temporary of type ‘A’
test.cpp:6: error: in passing argument 1 of ‘void foo(A&)’

在一些反映,这些错误使大量的意义对我来说。 A()只是暂时的价值,而不是在堆栈上分配的位置,所以它似乎不会有一个地址。如果没有一个地址,我就不能坚持对它的引用。好,好。

别急!如果我下面的转换运算符添加到类A

class A
{
public:
  operator A&() { return *this; }
};

就万事大吉!我的问题是,这是否甚至远程安全。究竟是什么this点时A()构造为临时值?

我给出了一些信心的事实,

void foo(const A&) {}

可以根据g++,我已经使用的所有其他的编译器接受临时值。该const关键字总是可以被抛弃,所以如果有一个const A&参数和A&参数之间的任何实际的语义差异,将让我感到吃惊。所以我想这是问我的问题的另一种方式:为什么是const参考编译器,而一个非const参考被认为是安全的临时值未

有帮助吗?

解决方案

这并不是说一个地址不能采取(编译器总是可以命令它推入堆栈,它与REF给const确实上),这是程序员意图的问题。与需要A&接口,它是说:“我会修改什么是该参数,以便能够在函数调用后读”。如果你传递一个临时的,那么事情就“修饰”并不功能后存在。这是(可能)一个编程错误,所以这是不允许的。例如,考虑:

void plus_one(int & x) { ++x; }

int main() {
   int x = 2;
   float f = 10.0;

   plus_one(x); plus_one(f);

   cout << x << endl << f << endl;
}

此不编译,但如果临时变量可以结合一个引用到非const,这将编译,但具有令人惊讶的结果。在plus_one(F)中,f将被隐式转换为一个临时INT,plus_one将采取临时和增加它,而使底层的浮子˚F不变。当plus_one回来,它不会有任何影响。这是几乎可以肯定不是编程人员意图。


该规则偶尔不弄乱。一个常见的例子(描述此处) ,试图打开一个文件,打印的东西,并关闭它。你会希望能够做到:

ofstream("bar.t") << "flah";

但你不能因为经营者<<需要一个裁判对非const。您的选项被打破它分成两行,或调用方法返回一个参考到非const:

ofstream("bar.t").flush() << "flah";

其他提示

当分配的r值以const引用,可以保证的是,临时不会被破坏直到参考被破坏。当分配给一个非const参考,没有这样的保证是由

int main()
{
   const A& a2= A(); // this is fine, and the temporary will last until the end of the current scope.
   A& a1 = A(); // You can't do this.
}

您不能安全地抛弃常量性威利愿意不愿意和期望事情的工作。有关于const和non-const的引用不同的语义。

这是一些人可能碰上疑难杂症:MSVC的编译器(Visual Studio的编译器,与Visual Studio 2008验证)的将会的编译这段代码,没有任何问题。我们一直在使用这种模式的项目,通常把一个参数(数据块消化)的功能,但有时想查询块和产量的结果返回给调用者。另一种模式是通过采取三个参数启用---第二个参数是信息(默认引用空字符串)搜索,第三个参数是为返回的数据(默认参照所需类型的空列表)。

这个范例,Visual Studio 2005和2008年的工作,我们不得不重构它使列表建成并返回,而不是拥有按主叫和突变与克至++编译。

如果有一种方法的编译器开关设置为禁止这种行为在MSVC或允许它以g ++,我会兴奋知道; g ++编译器的编译器MSVC /限制程度的放任增加并发症移植代码。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top