C++对象的拷贝与赋值操作

原创 2006年06月15日 13:19:00
我发现一些同事在编写一个类时,知道什么时候需要实现拷贝构造函数和赋值操作,但不知道什么时候拷贝构造函数被调用,什么时候赋值操作被调用,甚至把二者混为一谈。
 
要弄明白这个问题,最简单的做法莫过于写个测试程序试一下。不过那样做也未必是好办法,实验的结果往往导致以偏概全的结论。不如好好想一下,弄清楚其中的原理,再去写程序去验证也不迟。
 
拷贝构造函数,顾名思义,等于拷贝 + 构造。它肩负着创建新对象的任务,同时还要负责把另外一个对象拷贝过来。比如下面的情况就调用拷贝构造函数:
CString str = strOther;
 
赋值操作则只含有拷贝的意思,也就是说对象必须已经存在。比如下面的情况会调用赋值操作。
str = strOther;
 
不过有的对象是隐式的,由编译器产生的代码创建,比如函数以传值的方式传递一个对象时。由于看不见相关代码,所以不太容易明白。不过我们稍微思考一下,就会想到,既然是根据一个存在的对象拷贝生成新的对象,自然是调用拷贝构造函数了。
 
两者实现时有什么差别呢?我想有人会说,没有差别。呵,如果没有差别,那么只要实现其中一个就行了,何必要两者都实现呢?不绕圈子了,它们的差别是:
 
拷贝构造函数对同一个对象来说只会调用一次,而且是在对象构造时调用。此时对象本身还没有构造,无需要去释放自己的一些资源。而赋值操作可能会调用多次,你在拷贝之前要释放自己的一些资源,否则会造成资源泄露。
 
明白了这些道理之后,我们不防写个测试程序来验证一下我们的想法:
 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
classCString
{  
public:
    CString();
    CString(constchar* pszBuffer);
    ~CString();
    CString(constCString& other);
    constCString& operator=(constCString& other);
 
private:
    char* m_pszBuffer;;
}; 
 
CString::CString()
{
    printf("CString::CString/n");
    m_pszBuffer = NULL;
 
    return;
}  
       
CString::CString(constchar* pszBuffer)
{
    printf("CString::CString(const char* pszBuffer)/n");
    m_pszBuffer = pszBuffer != NULL ? strdup(pszBuffer) : NULL;
 
    return;
}
CString::~CString()
{
    printf("%s/n", __func__);
    deletem_pszBuffer;
    m_pszBuffer = NULL;
 
    return;
}
 
CString::CString(constCString& other)
{
    if(this == &other)
    {
        return;
    }
 
    printf("CString::CString(const CString& other)/n");
    m_pszBuffer = other.m_pszBuffer != NULL ? strdup(other.m_pszBuffer) : NULL;
}
 
constCString& CString::operator=(constCString& other)
{
    printf("const CString& CString::operator=(const CString& other)/n");
 
    if(this == &other)
    {
        return *this;
    }
 
    if(m_pszBuffer != NULL)
    {
        free(m_pszBuffer);
        m_pszBuffer = NULL;
    }
         m_pszBuffer = other.m_pszBuffer != NULL ? strdup(other.m_pszBuffer) : NULL;
 
    return *this;
}
 
voidtest(CStringstr)
{
    CStringstr1 = str;
 
    return;
}
 
intmain(intargc, char* argv[])
{
    CStringstr;
    CStringstr1 = "test";
    CStringstr2str1;
    str1 = str;
 
    CStringstr3 = str3;
 
    test(str);
 
    return 0;
}

C++IO对象不可复制或赋值

C++IO对象不可复制或赋值IO类型的3个独立的头文件:iostream定义读写控制窗口的类型,fstream 定义读写已命名文件的类型, (包含fstream类)sstrea...
  • crazy_father
  • crazy_father
  • 2015年06月27日 13:03
  • 713

深入C++的拷贝构造和赋值函数 (深拷贝,浅拷贝)

参考了:点击打开链接以及《高质量程序设计指南C++/C语言》 说明 拷贝构造函数是一种特殊的构造函数。相同类型的类对象是通过拷贝构造函数来完成整个复制过程的。 函数的名称必须和类名称一致。 它...
  • ywok526
  • ywok526
  • 2014年08月13日 11:54
  • 1074

C++本质:类的赋值运算符=的重载,以及深拷贝和浅拷贝(收藏)

关键词:构造函数,浅拷贝,深拷贝,堆栈(stack),堆heap,赋值运算符 摘要:     在面向对象程序设计中,对象间的相互拷贝和赋值是经常进行的操作。     如果对象在申明的同时马上进行...
  • business122
  • business122
  • 2014年03月14日 17:13
  • 1557

C++如何禁止掉对象的复制操作

最容易想到的是将拷贝构造函数与赋值函数声明为private。但是,private只是说外部不能直接调用,但是可以间接通过类的成员函数来调用(通过成员函数与友元函数对其访问)。那么怎么办呢? ----》...
  • a627088424
  • a627088424
  • 2015年05月28日 11:12
  • 1641

C++【拷贝构造】和【拷贝赋值】(实现自定义的string类)

拷贝构造的形式,何种情况会调用拷贝构造。 1.构造副本 2.以值的方式传参 3.以值的方式返回缺省的拷贝赋值只能实现浅拷贝,因此会带来对象与其副本之间的指针耦合问题,为了实现深拷贝,就需要自己定...
  • u010193457
  • u010193457
  • 2015年10月27日 14:10
  • 1387

C++ 深拷贝与浅拷贝&重载赋值运算符

在C++类的成员变量中存在指针变量的时候,就会存在深拷贝和浅拷贝问题。当使用C++编译器默认提供的拷贝构造函数或者对象的赋值操作的时候就会出现浅拷贝...
  • mr_ahke
  • mr_ahke
  • 2016年08月04日 20:22
  • 336

C++类四个默认函数---构造函数、析构函数、拷贝函数、赋值函数

默认构造函数指不带参数或者所有参数都有缺省值的构造函数!!! (1)构造函数、析构函数与赋值函数 构造函数、析构函数与赋值函数是每个类最基本的函数。它们太普通以致让人容易麻痹大意, ...
  • twlkyao
  • twlkyao
  • 2013年06月16日 09:09
  • 13339

C++中引用(&)的用法和拷贝/赋值函数的区别

习惯使用C进行开发的朋友们,在看到c++中出现的&符号,可能会犯迷糊,因为在C语言中这个符号表示了取地址符,但是在C++中它却有着不同的用途,掌握C++的&符号,是提高代码执行效率和增强代码质量的一个...
  • KingCat666
  • KingCat666
  • 2015年04月03日 10:52
  • 6623

对象的赋值、对象的复制(拷贝构造函数)

对象的赋值、对象的赋值
  • sinat_34608734
  • sinat_34608734
  • 2017年04月25日 20:26
  • 881

C++容器的拷贝注意细节

为了创建一个容器为另一个容器的拷贝,两个容器的类型以及元素类型必须匹配。当传递参数为两个迭代参数用来拷贝时,就不需要容器类型是相同的了,而且严肃类型也不要求是相同的,只需要将考别的严肃转换为对应的元素...
  • gu_gu_
  • gu_gu_
  • 2015年11月27日 10:27
  • 1122
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:C++对象的拷贝与赋值操作
举报原因:
原因补充:

(最多只允许输入30个字)