构造函数有哪几种,需要注意的问题 | c++ 进阶学习一条龙(三)

深度分析构造函数,带你了解隐式转换,深拷贝浅拷贝,以及c++11的移动构造函数,不需要长篇大论的文章,几个测试实例轻松解决 

#include <iostream>
using namespace std;

class student
{
    int age;
    int num;
public:
    //默认构造
    student();
    //有参构造
    student(int age,int num);
    //拷贝构造
    student(student& stu);
    //转换构造
    student(int age);
    //移动构造
    student(student&& stu);
    void getstu();
    void setstu();
    ~student();

};
student::student()
{
    this->age = 18;
    this->num = 0;
}

student::student(student& stu)
{
    cout << "transform" << endl;
    this->age = stu.age;
    this->num = stu.num;
}

student::student(int age, int num)
{
    this->age = age;
    this->num = num;
}

student::student(int age)
{
    cout << "transform" << endl;
    this->age = age;
    this->num = 666;
}

student::student(student&& stu)
{
    cout << "move" << endl;
    this->age = stu.age;
    this->num = stu.num;
}

void student::getstu()
{
    cout << this->age << "  " << this->num << endl;
}

void student::setstu()
{
    this->age = 0;
    this->num = 0;
}

student::~student()
{
    cout << "destroy" << endl;
}

示例一

int main()
{
    student stu1=666;//隐式调用单个参数的构造函数(转换构造)
    student stu2=stu1;//隐式调用拷贝构造,这里是深拷贝
    stu1.getstu();
    stu2.getstu();
    stu2.setstu();//修改stu的成员变量
    stu1.getstu();
    stu2.getstu();

}

结果

这里打印2个transform说明分别走了转换构造和拷贝构造,且为深拷贝,因为我修改了stu2的值后,stu1的值并没有发生改变。

这里我借此一句话总结浅拷贝和深拷贝的区别,浅拷贝只是复制了另一个对象的指针,最后两个对象同时指向一个内存空间,一个对象修改,另一个也会受到影响。深拷贝就是连内存空间都复制了,两个对象不会互相影响。 

示例二

int main()
{
    student* stu1 = new student();//默认构造
    student* stu2 = stu1;//浅拷贝
    stu1->getstu();
    stu2->getstu();
    stu2->setstu();
    stu1->getstu();
    stu2->getstu();
    return 0;
}

 这里用构造对象指针,居然不走拷贝构造了,而且是浅拷贝,stu1,stu2,公用一个内存空间,所一说编译器很奇怪,一会这样一会那样,因此为避免这种情况,我们需要在单参数构造函数前加上explicit关键字以防止隐式转换。

class student
{
    int age;
    int num;
public:
    //默认构造
    student();
    //有参构造
    student(int age,int num);
    //拷贝构造
    explicit student(student& stu);
    //转换构造
    explicit student(int age);
    void getstu();
    void setstu();

};

这样我就不可能用=去实例化对象,避免了一些异常情况的发生。

而且在测试时我使用qt的编译器测试时

student stu1=10;

这种情况是不被允许的,因为这涉及到了右值引用的问题

c++面试摘录(三) | 右值引用_无规则编程程序员的博客-CSDN博客

 所以说就是规规矩矩写正常的构造函数,加上关键字以防止隐式转换,就不会出那么多问题。

c++98/03的构造函数讲完了,还剩最后一个c++11的新构造函数移动构造函数

其实和移动构造和拷贝构造很像,但还是有差别,拷贝构造,会额外复制一个临时对象,会占用内存,在拷贝结束后析构,这样既费时又会消耗内存,因此移动构造应运而生。

移动构造的参数是一个右值对象,右值是什么可以看上面的链接。并可以借助于move函数;move函数的作用是把一个左值转成右值。move函数下的移动构造,可以直接将要拷贝对象的内存拿来用,而不用构造一个临时对象。移动构造性能上优于拷贝构造。

示例三

int main()
{
    student stu1(100, 100);
    student stu2(move(stu1));
    stu2.getstu();
    stu1.getstu();
    return 0;
}

 这里要注意的是按照move的作用会把stu1的内存给stu2,然后stu1会销毁,但事实上它到函数结束才调用析构,是因为只有在stu2离开了自己的作用域的时候才会析构,所以,如果继续使用stu2的变量,可能会发生意想不到的错误。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值