可以返回临时变量1C++中的NRVO编程语言闲话编程Contents可以返回临时变量 ..................................................................................... 1不要返回临时变量的引用 ............................................................................. 2NRVO机制 ............................................................................................ 2对于这种需要精细管理对象的语言来说有时候真是比较复杂,一个看似简单的问题一直在困惑着我:到底可不可以在方法中返回局部变量呢?可以返回临时变量答案是肯定的,如果我们在一个方法中返回了临时变量,这个临时变量实际上是在栈里面的,当执行完方法后栈就销毁了,那么为什么我们还可以这样做呢?来看一个例子:#include <iostream>using namespace std;class Value { public: Value(int _m):m(_m) { std::cout << "test constructor" << m << std::endl; } Value(const Value& t) { std::cout << "test copy constructor" << m << std::endl; this->m = t.m; } ~Value() { std::cout << "test destructor" << m << std::endl; } void print() { std::cout << "m:" << m << std::endl; } private: int m;};class Producer {public: Value produce(int i) { Value t(i); return t; }};int main(int argc, char* argv[]) { std::cout << "Hello world!" << std::endl; Producer p; Value t = p.produce(100); t.print(); return 1;}执行的结果是: NRVO机制2Hello world!test constructor100m:100test destructor100结果证明这样做其实是可以取到我们定义的值的,这么做可行的原因是,实际上,编译器会帮我们把临时变量拷贝一份出来,所以即便栈销毁了,我们也能够拿到新的值。不要返回临时变量的引用那么,如果我们返回临时变量的引用呢?class Producer {public: Value* produce(int i){ Value t(i); return &t; }};这样做得到的结果是不对的:test.cpp:21:17: warning: address of stack memory associated with local variable 't' returned [-Wreturn-stack-address] return &t; ^1 warning generated.Hello world!test constructor100test destructor100m:-327065280编译器会有一个警告,尽管我们仍旧可以运行我们的代码,但是实际上我们得到的值是不对的。NRVO机制那么,既然我们返回临时对象的值,实际上会得到一个拷贝的对象,那么如果我们有拷贝构造函数,是不是应该被调用呢?然而在前面的例子中,拷贝构造函数并没有被调用到,这又是为什么呢?答案就是因为。这是中的特性。我们首先可以尝试禁用掉这个特性,看看会发生什么。hfli@CNhfli ~ $ g++ -fno-elide-constructors test.cpphfli@CNhfli ~ $ ./a.outHello world!test constructor100test copy constructor0test destructor100test copy constructor0test destructor100 NRVO机制3m:100test destructor100可以看出,拷贝构造函数调用了两次,第一次是在函数中返回的时候,第二次是我们在给变量赋值的时候。