c++临时对象绑定到实参并返回const引用值
C++ temporary object bound to argument and return value const references
我无法清楚地知道这是否合法,即使在看了SO的相关问题并阅读了c++ 03标准第192页(http://cs.nyu.edu/courses/fall11/CSCI-GA.2110-003/documents/c++2003std.pdf)之后。
const MyClass& f(const MyClass& arg) {
return arg;
}
void some_other_function() {
const MyClass& reference = f(MyClass());
// Use reference.
}
据我所知,你不能这样做。虽然将临时对象绑定到const引用在c++中是合法的(并且会延长该临时对象的生命周期——参见GOTW 88),但将const ref进一步绑定到另一个const ref并不会延长该临时对象的生命周期。
引用自第192页(c++ 03标准):
函数调用中与引用形参的临时绑定(5.2.2)的完整表达式完成之前一直持续叫
我认为标准非常明确,在// Use reference.
之后使用reference是无效的。我修改了你的代码片段来检查它(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;
}
输出:
f()
~MyClass()
main()
换句话说,除非我和clang开发人员都误解了c++标准,否则它是非法的。
我无法从标准中得到一个明确的解释,所以我决定检查一下事实上的标准是什么。以下代码:
#include <cstdio>
struct MyClass
{
MyClass() { printf("constructorn"); }
~MyClass() { printf("destructorn"); }
MyClass(const MyClass&) { printf("copyn"); }
MyClass(MyClass&&) { printf("moven"); }
};
const MyClass& f(const MyClass& arg) {
return arg;
}
int main()
{
{
printf("before constructionn");
const MyClass& reference = f(MyClass());
printf("after constructionn");
}
printf("outside scopen");
}
收益率:
before construction
constructor
destructor
after construction
outside scope
适用于MSVC、clang和g++。根据我们的主要编译器供应商,这似乎是不合法的。
这个问题类似于下面的问题:到std::map
的操作符[]下面的代码解释了到底发生了什么
#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;
}
这个程序的输出将是:
Executing the program....
$demo
-----Faulty Case-----------
MyClass ctr
MyClass dtr
func -1
-----Correct way-----------
MyClass ctr
func 0
MyClass dtr
相关文章:
- 从函数返回const char*数组
- 为什么我不能在返回 const 的布尔函数中为类成员变量赋值?C++
- 从内部使用静态 std::string 的函数返回 const char * 是否安全?
- 从类方法返回 "const char*" 作为 std::string&
- 为什么const rvalue合格的std ::可选:: value()返回const rvalue参考
- 通过移动分配从算术运算符过载中返回const值
- 从本机代码返回"const char*"并在java中获取"字符串"
- 为什么我的C 函数拒绝返回const引用
- 通过参考返回和const函数返回const值的函数之间的差异
- 如果我返回const定义的对象,为什么const关键字被取消资格
- 返回const lvalue引用rvalue临时?为什么这项工作
- 内置类型的返回const值
- 返回 const std::string*& from a std::string *tab[11]
- 如何在静态方法中返回const类型
- 返回const引用和非常数成员函数调用
- 为什么不允许我将函数返回 const char* 的结果分配给 char*,bt 可以将字符串文字(常量)分配给 cha
- 在 C++ 中返回 const 字符串引用的字符串文本
- 为什么我们必须从一元前缀运算符重载返回 const 引用
- 在返回 const 错误的函数中传递值
- 为什么我可以将返回 'const T&' 的函数的返回值分配给 'T' 变量,而不是 'T&' 变量?