先吃栗子
//otherobjec.h
#include <iostream>
class OtherObject {
public:
static int iCount;
int id;
OtherObject() {
id = iCount++;
std::cout << this->id << ":OtherObject():" << std::endl;
}
OtherObject(int value) {
id = iCount++;
std::cout << this->id << ":OtherObject(int):" << std::endl;
}
OtherObject(const OtherObject& b) {
id = iCount++;
std::cout << this->id << ":OtherObject(&):" << std::endl;
}
OtherObject(OtherObject&& b) {
id = iCount++;
std::cout << this->id << ":OtherObject(&&):" << std::endl;
}
OtherObject& operator=(const OtherObject& b) {
std::cout << this->id << ":OtherObject=(&):" << std::endl;
return *this;
}
OtherObject& operator=(OtherObject&& b) {
std::cout << this->id << ":OtherObject=(&&):" << std::endl;
return *this;
}
std::shared_ptr<int> value{ nullptr };
~OtherObject() {
std::cout << this->id << ":~OtherObject():" << std::endl;
}
};
int OtherObject::iCount = 100;
//myclass.h
#include "otherobject.h"
class MyClass {
public:
static int iCount;
int id;
MyClass() {
id = iCount++;
std::cout << this->id << ":MyClass():" << std::endl;
}
MyClass(const MyClass& b) {
id = iCount++;
std::cout << this->id << ":MyClass(&):" << std::endl;
}
MyClass(MyClass&& b) {
id = iCount++;
std::cout << this->id << ":MyClass(&&):" << std::endl;
}
MyClass& operator=(const MyClass& b) {
std::cout << this->id << ":MyClass=(&):" << std::endl;
return *this;
}
MyClass& operator=(MyClass&& b) {
std::cout << this->id << ":MyClass=(&&):" << std::endl;
return *this;
}
std::shared_ptr<int> value{ nullptr };
~MyClass() {
std::cout << this->id << ":~MyClass():" << std::endl;
}
OtherObject innerObj{};
OtherObject returnNewObject1() {
std::cout << this->id << ":calling method 1: OtherObject returnNewObject1() { return OtherObject(); }" << std::endl;
return OtherObject();
}
OtherObject returnNewObject2() {
std::cout << this->id << ":calling method 2: OtherObject returnNewObject2() { OtherObject obj{};return obj; }" << std::endl;
OtherObject obj{};
return obj;
}
const OtherObject& returnNewObject3() {
std::cout << this->id << ":calling method 3: const OtherObject& returnNewObject3() { OtherObject obj{};return obj; }" << std::endl;
OtherObject obj{};
return obj;
}
OtherObject returnInnerObject() {
std::cout << this->id << ":calling method 4: OtherObject returnInnerObject() { return innerObj }" << std::endl;
return innerObj;
}
const OtherObject& returnRefFromInnerObject() {
std::cout << this->id << ":calling method 5: const OtherObject& returnRefFromInnerObject() { return innerObj; }" << std::endl;
return innerObj;
}
};
int MyClass::iCount = 200;
//main.cpp
#include "myclass.h"
int main(int argc, char *argv[])
{
{
MyClass myClass{};
std::cout << "-------------------------------------------------------------------" << std::endl;
std::cout << std::endl << "[" << __LINE__ << "]OtherObject newObj1 = myClass.returnNewObject1();" << std::endl;
OtherObject newObj1 = myClass.returnNewObject1();
std::cout << std::endl << "[" << __LINE__ << "]OtherObject newObj2 = myClass.returnNewObject2();" << std::endl;
OtherObject newObj2 = myClass.returnNewObject2();
std::cout << std::endl << "[" << __LINE__ << "]OtherObject innerObj = myClass.returnInnerObject();" << std::endl;
OtherObject innerObj = myClass.returnInnerObject();
std::cout << std::endl << "[" << __LINE__ << "]OtherObject refInnerObj = myClass.returnRefFromInnerObject();" << std::endl;
OtherObject refInnerObj = myClass.returnRefFromInnerObject();
std::cout << std::endl << "[" << __LINE__ << "]const OtherObject& constRefInnerObj = myClass.returnRefFromInnerObject();" << std::endl;
const OtherObject& constRefInnerObj = myClass.returnRefFromInnerObject();
std::cout << std::endl << "[" << __LINE__ << "]newObj1 = myClass.returnNewObject();" << std::endl;
newObj1 = myClass.returnNewObject1();
std::cout << std::endl << "[" << __LINE__ << "]newObj2 = myClass.returnNewObject();" << std::endl;
newObj2 = myClass.returnNewObject2();
std::cout << std::endl << "[" << __LINE__ << "]innerObj = myClass.returnInnerObject();" << std::endl;
innerObj = myClass.returnInnerObject();
std::cout << "-------------------------------------------------------------------" << std::endl;
}
return 0;
}
输出:
100:OtherObject():
200:MyClass():
-------------------------------------------------------------------
[124]OtherObject newObj1 = myClass.returnNewObject1();
200:calling method 1: OtherObject returnNewObject1() { return OtherObject(); }
101:OtherObject():
[126]OtherObject newObj2 = myClass.returnNewObject2();
200:calling method 2: OtherObject returnNewObject2() { OtherObject obj{};return obj; }
102:OtherObject():
103:OtherObject(&&):
102:~OtherObject():
[128]OtherObject newObj3 = myClass.returnNewObject3();
200:calling method 3: const OtherObject& returnNewObject3() { OtherObject obj{};return obj; }
104:OtherObject():
104:~OtherObject():
105:OtherObject(&):
[130]const OtherObject& constNewObj3 = myClass.returnNewObject3();
200:calling method 3: const OtherObject& returnNewObject3() { OtherObject obj{};return obj; }
106:OtherObject():
106:~OtherObject():
[132]OtherObject innerObj = myClass.returnInnerObject();
200:calling method 4: OtherObject returnInnerObject() { return innerObj }
107:OtherObject(&):
[134]OtherObject refInnerObj = myClass.returnRefFromInnerObject();
200:calling method 5: const OtherObject& returnRefFromInnerObject() { return innerObj; }
108:OtherObject(&):
[136]const OtherObject& constRefInnerObj = myClass.returnRefFromInnerObject();
200:calling method 5: const OtherObject& returnRefFromInnerObject() { return innerObj; }
[138]newObj1 = myClass.returnNewObject1();
200:calling method 1: OtherObject returnNewObject1() { return OtherObject(); }
109:OtherObject():
101:OtherObject=(&&):
109:~OtherObject():
[140]newObj2 = myClass.returnNewObject2();
200:calling method 2: OtherObject returnNewObject2() { OtherObject obj{};return obj; }
110:OtherObject():
111:OtherObject(&&):
110:~OtherObject():
103:OtherObject=(&&):
111:~OtherObject():
[142]newObj3 = myClass.returnNewObject3();
200:calling method 3: const OtherObject& returnNewObject3() { OtherObject obj{};return obj; }
112:OtherObject():
112:~OtherObject():
105:OtherObject=(&):
[144]innerObj = myClass.returnInnerObject();
200:calling method 4: OtherObject returnInnerObject() { return innerObj }
113:OtherObject(&):
107:OtherObject=(&&):
113:~OtherObject():
-------------------------------------------------------------------
108:~OtherObject():
107:~OtherObject():
105:~OtherObject():
103:~OtherObject():
101:~OtherObject():
200:~MyClass():
100:~OtherObject():
结论:
1.方法需要返回新对象时,返回值不能是引用类型,否则某些情况下会出问题;(见[130]输出结果,返回值已被析构)
2.尽量在return语句创建返回的对象,否则会带来移动复制和析构的开销;(见[124]~[130]输出结果)
3.需要返回内部对象时,返回值设置为const引用,并将接受该对象的对象也定义为const引用,否则会带来复制构造的开销;(见[132]~[136]输出结果)
4.在需要返回值时定义并调用获取对象的方法,否则会带来移动赋值的开销;(见[138]~[144]输出结果)