Ben*_*Ben 14 c++ reference operators type-conversion operator-keyword
当我使用编译以下代码时 g++
class A {};
void foo(A&) {}
int main()
{
foo(A());
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我收到以下错误消息:
> 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&)’
Run Code Online (Sandbox Code Playgroud)
经过一番反思,这些错误对我来说很有意义.A()只是一个临时值,而不是堆栈中的可分配位置,因此它似乎没有地址.如果它没有地址,那么我就不能对它进行引用.好的.
可是等等!如果我将以下转换运算符添加到类中A
class A
{
public:
operator A&() { return *this; }
};
Run Code Online (Sandbox Code Playgroud)
一切都很好!我的问题是这是否远程安全.什么时候this指向何时A()构建为临时值?
事实上,我对此充满信心
void foo(const A&) {}
Run Code Online (Sandbox Code Playgroud)
可以根据g++我使用过的所有其他编译器接受临时值.该const关键字总是可以被抛弃,所以如果有一之间的任何实际的语义差异,将让我感到吃惊const A&参数和A&参数.所以我猜这是另一种问我问题的方式:为什么const编译器认为安全的临时值是const引用而非引用不是?
Tod*_*ner 16
这不是一个地址不能被采用(编译器可以总是命令它在堆栈上推送它,它与ref-to-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;
}
Run Code Online (Sandbox Code Playgroud)
这不会编译,但如果temporaries可以绑定到ref-to-non-const,它会编译但会产生令人惊讶的结果.在plus_one(f)中,f将被隐式转换为临时int,plus_one将获取temp并递增它,使底层float f保持不变.当plus_one返回时,它将没有任何效果.这几乎肯定不是程序员的意图.
该规则偶尔会搞砸.一个常见的例子(这里描述),试图打开一个文件,打印一些东西,然后关闭它.你希望能够做到:
ofstream("bar.t") << "flah";
Run Code Online (Sandbox Code Playgroud)
但你不能因为运算符<<取一个ref-to-non-const.你的选择是将它分成两行,或者调用一个返回ref-to-non-const的方法:
ofstream("bar.t").flush() << "flah";
Run Code Online (Sandbox Code Playgroud)
当您将 r 值分配给 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.
}
Run Code Online (Sandbox Code Playgroud)
你不能安全地随意抛弃常量性并期望事情能奏效。const 和非常量引用有不同的语义。
| 归档时间: |
|
| 查看次数: |
10614 次 |
| 最近记录: |