DoubleLi

qq: 517712484 wx: ldbgliet

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::
  4737 随笔 :: 2 文章 :: 542 评论 :: 1615万 阅读
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

一、前言
写一个用到指针的程序时,被拷贝、赋值、析构函数坑了一波,网上查相关博客,发现关于拷贝、赋值构造函数调用时机大多都有错误,因此决定自己总结撸一发博客。

A (A& a);                        //拷贝构造函数
A (const A& a);                    //拷贝构造函数
A& operator= (const A& a);        //赋值构造函数
先写一个类,用作之后的示例

class A {
public:
    int* x;
    int y;
    A() = default;
    A (const A& a) {
        printf ("拷贝构造\n");
        this->x = a.x;
        this->y = a.y;
    }

    A& operator= (const A& a) {
        printf ("赋值构造\n");
        this->x = a.x;
        this->y = a.y;
    }
    A (int t) {
        x = new int (0);
        y = t;
        printf ("address: %x, point: %x, value: %d\n", this, x, y);
    }
    ~A() {
        printf ("delete %x\n", this);
    }
};

A f () {
    A ret (3);
    printf ("stack address: %x, point: %x, value: %d\n", &ret, ret.x, ret.y);
    return ret;
}

二、拷贝构造函数
1.对象需要通过另外一个对象进行初始化

int main() {
    A a(1);
    A c = a;
    printf ("global address: %x, point: %x, value: %d\n", &c, c.x, c.y);
    return 0;
}

2.对象通过值传递方式进入函数

void g (A ret) {
    printf ("stack address: %x, point: %x, value: %d\n", &ret, ret.x, ret.y);
}

int main() {
    A a (1);
    g (a);
    return 0;
}

3.当对象以值传递的方式从函数返回

class A {
public:
    int* x;
    int y;
    A() = default;
    A (const A& a) = delete; //注意把拷贝构造设为禁止使用

    A (int t) {
        x = new int (0);
        y = t;
        printf ("address: %x, point: %x, value: %d\n", this, x, y);
    }
    ~A() {
        printf ("delete %x\n", this);
    }
    A& operator= (const A& a) {
        printf ("赋值构造\n");
        this->x = a.x;
        this->y = a.y;
    }
};

A f () {
    A ret (3);
    printf ("stack address: %x, point: %x, value: %d\n", &ret, ret.x, ret.y);
    return ret;
}
int main() {
    A c = f(); 
    printf ("global address: %x , point: %x, value: %d\n", &c, c.x, c.y);
    return 0;
}

编译时发生错误,提示return ret调用了被禁止使用的拷贝构造函数

三、赋值构造函数
1.对象以值传递方式从函数返回,且接受返回值的对象已经初始化过

int main() {
    A c;
    c = f();
    printf ("global address: %x, point: %x, value: %d\n", &c, c.x, c.y);
    return 0;
}

2.对象直接赋值给另一个对象,且接受值的对象已经初始化过

int main() {
    A a(1);
    A c;
    c = a;
    printf ("global address: %x, point: %x, value: %d\n", &c, c.x, c.y);
    return 0;
}


四、总结
对象以值传递方式从函数返回时,若接受返回值的对象已经初始化过,则会调用赋值构造函数,且该对象还会调用析构函数,当对象中包含指针时,会使该指针失效,因此需要重载赋值构造函数,使用类似深拷贝或移动构造函数的方法赋值,才能避免指针失效。

posted on   DoubleLi  阅读(162)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
历史上的今天:
2021-01-21 inux top命令的用法详细详解
2021-01-21 mysql占用CPU超过100%解决过程
2019-01-21 vld for memory leak detector (release version)
2019-01-21 在Release版本下使用VLD
2015-01-21 CURL 和LIBCURL C++代码 上传本地文件,好不容易碰到了这种折腾我几天的代码
2014-01-21 VS2008调试技巧收集备用
2013-01-21 c++读写文件和测试程序运行时间的例子
点击右上角即可分享
微信分享提示