2015-12-15 139 views
0

我开发简单的C++类来测试C++对象何时销毁;现在我有一个问题,当一个对象按函数返回时,C++创建一个新对象并返回该对象,并在返回引用时销毁对象,我的错误是什么?如何在不创建副本的情况下返回对象?

简单的类如下所示。

#include <iostream> 

using namespace std; 

static int freeCounter=0; 

class TestCopy { 
private: 
    string pStr; 
public: 
    TestCopy(const TestCopy &obj){ 
     pStr=obj.pStr; 
    } 
    TestCopy(string &test){ 
     pStr=test; 
    } 
    ~TestCopy(){ freeCounter++; cout << freeCounter <<"\t" << pStr << endl; } 

    TestCopy get(){ 
     TestCopy x=*this; 
     return TestCopy(x); // -> TestCopy(x) is first destroy in result 
    } 

    string getStr(){ 
     return pStr; 
    } 
}; 

int main(){ 
    string xstr="test"; 
    TestCopy x(xstr); // x is third destroy 
    TestCopy x2=x.get(); // x2 is second destroy 

    cout << x.getStr() << endl; 

    return 0; 
} 

,并导致功能获取

1 test 
test 
2 test 
3 test 
+0

的问题是,这些都不'TestCopy'are的动态分配的,所以当超出范围,他们被摧毁。 – Rodolfo

+0

你必须明确地说,你正在函数签名'TestCopy&get(){'注意到'''我添加了 – Rodolfo

+1

并不完全正确,@Rodolfo。Copy elision会在返回问题时处理复制构造,并且返回本地作为参考将在MohsenTi的面部爆炸,因为返回的引用不再存在。 Moe on copy elision:http://stackoverflow.com/questions/12953127/what-are-copy-elision-and-return-value-optimization – user4581301

回答

-1

谢谢您的帮助,我发现我的错误@seaman。 通过改变

TestCopy x=*this; 

const TestCopy &x=*this; 

问题解决

+0

为什么当你说'return * this'时你需要'x'? – juanchopanza

1

x是一个本地对象,当函数结束时,X将被销毁。

所以,x是所述第一销毁。

0

首先OP的代码进行审查。我稍微修改了一下,以便更明显地发生。

#include <iostream> 

using namespace std; 

static int allocCounter = 0; 

class TestCopy 
{ 
private: 
    string pStr; 
    int counter; 
public: 
    TestCopy(const TestCopy &obj) 
    { 
     allocCounter++; 
     counter = allocCounter; 
     cout << "copy construct " << counter << endl; 
     pStr = obj.pStr; 
    } 
    TestCopy(const string &test) 
    { 
     allocCounter++; 
     counter = allocCounter; 
     cout << "string construct " << counter << endl; 
     pStr = test; 
    } 
    ~TestCopy() 
    { 
     cout << counter << "\t" << pStr << endl; 
    } 

    TestCopy get() 
    { 
     TestCopy x = *this; // copy constructed 
     return TestCopy(x); // copy constructed and copy elision 
    } 

    string getStr() 
    { 
     return pStr; 
    } 
    TestCopy & operator=(const TestCopy &obj) 
    { 
     cout << "assigned " << obj.counter << " to "<< counter << endl; 

     pStr = obj.pStr; 
//  counter = obj.counter; deliberately left out 
     return *this; 
    } 

}; 

int main() 
{ 
    string xstr = "test"; 
    TestCopy x(xstr); // string constructed 
    TestCopy x2 = x.get(); // Would be a copy constructed if not for copy elision 
    return 0; 
} 

输出

string construct 1 
copy construct 2 
copy construct 3 
2 test 
3 test 
1 test 

注意即使TestCopy x=*this;

好吧赋值操作符的呼叫。现在我们该如何砍掉一些呢?

首先我们得到get

TestCopy get() 
{ 
    return *this; // copy constructed. Or is it? The copy construction could 
        // happen at the caller. Either way it is copied and elided 
} 

输出

string construct 1 
copy construct 2 
2 test 
1 test 

所以去掉冗余副本在这一点上,我们知道有没有必要获取复制或分配,因为return语句会为我们做。这是关于OP的问题的重要部分。

但是,如果我们改变main了一下,添加一个赋值运算符,我们可以看到一个更有趣的行为。

int main() 
{ 
    string xstr = "test"; 
    TestCopy x(xstr); // string constructed 
    TestCopy x2(""); //string constructed 
    x2 = x.get(); // assigned and a copy construct when returning from get 
    cout << "done main" << endl; 
    return 0; 
} 

输出

string construct 1 
string construct 2 
copy construct 3 
assigned 3 to 2 
3 test 
done main 
2 test 
1 test 

get返回被分配到x2,然后销毁。 x2被破坏,最后x

相关问题