c++函数体内new对象时拷贝构造函数详解

当对象一般作为函数返回值时,一般会使用拷贝构造函数,然而在具体实现过程中,发现并没有通过拷贝构造函数来完成复制对象的工作,我们看一下例子。

#include <iostream>
#include <string>

using namespace std;

class Student
{

public:
    Student(int age, string name)
    {
        this->age = age;
        this->name = name;
    }

    Student (const Student& s)
    {
        cout<<"copy function"<<endl;
        this->age = s.age;
        this->name = s.name;
    }

     ~Student()
    {
        cout<<"discard a object address: "<<this<<endl;
    }

private:
    int age;
    string name;
};

Student student_say()
{
    Student stu(10,"lmt");
    cout<< "student in function address:"<<&stu<<endl;
    return stu;

}

int main()
{
    Student stu = student_say();
    cout<<"student in main function address: "<<&stu<<endl;

    return 0;
}

我们写了一个简单的类,并实现了拷贝构造函数,在使用拷贝构造函数处,会打印输出“copy function”。但这个程序的结果我们可以看一下:

函数里构建的对象地址和主函数里作为接受对象的地址一样,而且没有调用拷贝构造函数。why?

原因就在于编译器自行对其进行了优化,这里我们要了解函作为值返回时的操作。

  • 创建Student类对象stu;
  • main函数在栈额外开辟一片空间,并将这块空间的一部分作为传递返回值的临时对象,这里称为temp;
  • temp完成对Student(stu)的拷贝构造 ( Student temp(stu)),函数把temp地址传出至eax寄存器;
  • return返回以后,mian函数将eax 指向的temp对象的内容拷贝给main函数里的stu。

上述操作要完成三次对象的构造,函数内构造,栈内临时对象的构造,主函数里对象的构造,而函数内的构造和临时对象的构造会被析构,所以实际上只需一次构造即可,因此编译器优化后只是实现了一次构造函数

但如果我们仍然想看函数返回值调用拷贝构造函数的情况的话,需要在函数内new一个对象,不过这里存在着内存泄漏的风险。

Student student_say()
{
     Student *stu = new Student(10,"lmt");
     cout<<"in function"<<endl;
     cout<<"stu address"<<stu<<endl;
     return *stu;
}

函数执行结果如下:

按照我们之前的思路就是,函数内构建对象,main函数栈内构建临时对象,临时对象完成对函数内对象的构造,并将地址传出至eax,在主函数里,将eax寄存器传出的地址内容拷贝到函数对象。但是我们会发现new出的对象我们没法完成对它的析构操作。正事因为在函数里构建的变量在栈上,因此堆上new出的对象无法对其析构,因此编译器无法对这种情况做出优化,因为我们可以看到拷贝函数被调用了。如果我们想析构这这个对象,函数就需要用通过引用返回,再通过传回的引用来析构该对象了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值