关于c++ 返回值的类型定义选择及使用

先吃栗子

//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]输出结果)

  • 8
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值