[英]C++ temporary object bound to argument and return value const references
I cannot get a clear idea of whether this is legal, even after looking at related questions on SO and reading the C++03 standard page 192 ( http://cs.nyu.edu/courses/fall11/CSCI-GA.2110-003/documents/c++2003std.pdf ). 即使在查阅SO上的相关问题并阅读C ++ 03标准页面192( http://cs.nyu.edu/courses/fall11/CSCI-GA.2110)之后,我也无法清楚地知道这是否合法。 -003 / documents / c ++ 2003std.pdf )。 Is this legal and safe:
这是合法和安全的:
const MyClass& f(const MyClass& arg) {
return arg;
}
void some_other_function() {
const MyClass& reference = f(MyClass());
// Use reference.
}
It seems to me that it is. 在我看来它是。
As far as I know, you can't do this. 据我所知,你不能这样做。 While binding a temporary to a const reference is legal C++(and lengthens the lifetime of that temporary -- see GOTW 88 ), further binding a const ref to another const ref doesn't lengthen the lifetime of that temporary.
虽然将临时绑定到const引用是合法的C ++(并且延长了该临时的生命周期 - 请参阅GOTW 88 ),将const ref与另一个const ref进一步绑定并不会延长该临时值的生命周期。
The quote from page 192( C++03 standard ): 第192页的引用( C ++ 03标准 ):
A temporary bound to a reference parameter in a function call (5.2.2) persists until the completion of the full expression containing the call
在函数调用(5.2.2)中与引用参数的临时绑定将持续存在,直到包含该调用的完整表达式完成为止
I think the standard is pretty explicit that using reference after // Use reference.
我认为标准非常明确,在使用引用之后
// Use reference.
is invalid. 是无效的。 I modified your snippet to check it(Mac OS X, clang:
Apple LLVM version 5.1 (clang-503.0.40) (based on LLVM 3.4svn)
): 我修改了你的代码片段来检查它(Mac OS X,clang:
Apple LLVM version 5.1 (clang-503.0.40) (based on LLVM 3.4svn)
):
#include <iostream>
struct MyClass
{
~MyClass()
{
std::cout << "~MyClass()" << std::endl;
}
};
const MyClass& f(const MyClass& arg) {
std::cout << "f()" << std::endl;
return arg;
}
int main() {
const MyClass& reference = f(MyClass());
std::cout << "main()" << std::endl;
}
It outputs: 它输出:
f()
~MyClass()
main()
In other words, unless both me and clang developers are misinterpreting the C++ standard, it is illegal. 换句话说,除非我和clang开发人员都误解了C ++标准,否则它是非法的。
I was unable to get a clear interpretation from the standard, so I decided to check what's the de facto standard. 我无法从标准中得到明确的解释,所以我决定检查什么是事实上的标准。 The following code:
以下代码:
#include <cstdio>
struct MyClass
{
MyClass() { printf("constructor\n"); }
~MyClass() { printf("destructor\n"); }
MyClass(const MyClass&) { printf("copy\n"); }
MyClass(MyClass&&) { printf("move\n"); }
};
const MyClass& f(const MyClass& arg) {
return arg;
}
int main()
{
{
printf("before construction\n");
const MyClass& reference = f(MyClass());
printf("after construction\n");
}
printf("outside scope\n");
}
Yields: 产量:
before construction
constructor
destructor
after construction
outside scope
For MSVC, clang and g++. 对于MSVC,clang和g ++。 Seems it is not legal according to our main compiler suppliers.
根据我们的主要编译器供应商,它似乎不合法。
This question is similar to following question: Pass const Key_Type& to operator[] of std::map 这个问题类似于以下问题:将const const_Type&传递给std :: map的operator []
The code below explains what exactly is happening 下面的代码解释了究竟发生了什么
#include <iostream>
struct MyClass{
int member;
MyClass():member(0){
std::cout<<"MyClass ctr "<<std::endl;
}
MyClass(const MyClass& rhs){
std::cout<<"MyClass copy ctr "<<std::endl;
}
~MyClass(){
std::cout<<"MyClass dtr"<<std::endl;
member = -1;
}
};
void f2(const MyClass& obj){
std::cout<<"func "<<obj.member<<std::endl;
}
const MyClass& f3(){
return MyClass();
}
MyClass f4(){
return MyClass(); //ideally not a good idea, exception is
//http://herbsutter.com/2008/01/01/gotw-88-a-candidate-for-the-most-important-const/
}
int main()
{
std::cout << "-----Faulty Case-----------"<<std::endl;
//reference returned by f3 is local to f3 call and
//is destructed as soon as f3() is out of stack
//and hence the reference in f2() is not valid
f2( f3() );
std::cout <<std::endl<< "-----Correct way-----------"<<std::endl;
//A temporary object is returned by f4 which is then referred by reference in f2.
//This reference is alive in stack of f2 and hence can be used inside
//f2 with valid results.
//As explained in following article, the refernce should remain
//alive in stack to use temporary objects.
//http://herbsutter.com/2008/01/01/gotw-88-a-candidate-for-the-most-important-const/
f2( f4() );
//note in previous expression, f4 returns by value but still copy ctr is not invoked,
//this I believe is Return Value Optimization (might be compiler dependent)
return 0;
}
Output of this program would be: 该计划的产出将是:
Executing the program....
$demo
-----Faulty Case-----------
MyClass ctr
MyClass dtr
func -1
-----Correct way-----------
MyClass ctr
func 0
MyClass dtr
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.