如何在不创建副本的情况下 return 对象?
how to return object without create copy of that?
我开发了简单的 c++ class 来测试 c++ 对象何时销毁;现在我有一个问题,当对象 return 通过函数时,c++ 创建一个新对象并 return 并且当 return 引用销毁对象时我的错误是什么?
下面附上简单的class。
#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
get函数中的x是局部对象,当函数结束时,x会被销毁。
所以,x是第一个销毁的。
谢谢@seaman 的帮助,我发现了我的错误。
通过更改
TestCopy x=*this;
和
const TestCopy &x=*this;
问题已解决
首先回顾一下 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
所以此时我们知道不需要在 get 中进行复制或赋值,因为 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
的 return 被分配给 x2
,然后销毁。 x2
被摧毁,最后 x
.
我开发了简单的 c++ class 来测试 c++ 对象何时销毁;现在我有一个问题,当对象 return 通过函数时,c++ 创建一个新对象并 return 并且当 return 引用销毁对象时我的错误是什么?
下面附上简单的class。
#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
get函数中的x是局部对象,当函数结束时,x会被销毁。
所以,x是第一个销毁的。
谢谢@seaman 的帮助,我发现了我的错误。 通过更改
TestCopy x=*this;
和
const TestCopy &x=*this;
问题已解决
首先回顾一下 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
所以此时我们知道不需要在 get 中进行复制或赋值,因为 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
的 return 被分配给 x2
,然后销毁。 x2
被摧毁,最后 x
.