精华内容
下载资源
问答
  • 调用C++复制构造函数和拷贝构造函数来源:中国自学编程网 发布日期:2008-12-02 1. 何时调用复制构造函数 复制构造函数用于将一个对象复制到新创建的对象中。也就是说,它用于初始化过程中,而不是常规的赋值过程中...
    调用C++复制构造函数和拷贝构造函数
    来源:中国自学编程网   发布日期:2008-12-02  
    1. 何时调用复制构造函数

    复制构造函数用于将一个对象复制到新创建的对象中。也就是说,它用于初始化过程中,而不是常规的赋值过程中。类的复制构造函数原型通常如下:

    class_name(const class_name&);

    它接受一个指向类对象的常量引用作为参数。例如,String类的复制构造函数的原型如下:

    String(const String&);

    新建一个对象并将其初始化为同类现有对象时,复制构造函数都将被调用。这在很多情况下都可能发生,最常见的情况是将新对象显示地初始化为现有的对象。例如,假设motto是一个String对象,则下面4种声明都将调用复制构造函数:

    String ditto(motto);

    String metoo = motto;

    String also = String(motto);

    String *pString = new String(motto);

    其中中间的2种声明可能会使用复制构造函数直接创建metto和also,也可能会使用复制构造函数生成一个临时对象,然后将临时对象的内容赋给metoo和also,这取决于具体的实现。最后一种声明使用motto初始化一个匿名对象,并将新对象的地址赋给pString指针。

    2. 何时调用赋值构造函数

    赋值构造函数是通过重载赋值操作符实现的,这种操作符的原型如下:

    Class_name& Class_name::operator=(const Class_name&);

    它接受并返回一个指向类对象的引用。例如,String 类的赋值操作符的原型如下:

    String& String::operator=(const String&);

    将已有的对象赋给另一个对象时,将使用重载的赋值操作符:

    String headline1("test");

    String knot;

    knot = headline1;

    初始化对象时,并不一定会使用赋值操作符:

    String metoo = knot;

    这里,metoo是一个新创建的对象,被初始化为knot的值,因此使用复制构造函数。不过,正如前面指出的,实现时也可能分两步来处理这条语句:使用复制构造函数创建一个临时对象,然后通过赋值将临时对象的值复制到新对象中。这就是说,初始化总是会调用复制构造函数,而使用=操作符时也可能调用赋值操作符



    实例代码如下:

    #include <iostream>
    using namespace std;

    class Test
    {
    public:
    Test();
    ~Test();
    Test(const Test& t);
    Test& operator=(const Test& t);

    private:
    int t1;
    };

    Test::Test()
    {
    cout<<"调用构造函数"<<endl;
    }

    Test::~Test()
    {
    cout<<"调用析构函数"<<endl;
    }

    Test::Test(const Test& t)
    {
    cout<<"调用复制构造函数"<<endl;
    }

    Test& Test::operator =(const Test& t)
    {
    cout<<"调用赋值构造函数"<<endl;
    t1 = t.t1;
    return *this;
    }

    void main()
    {
    Test t1;
    Test t2 = t1;
    Test t3;
    t3 = t1;
    }


    输出如下:

    调用构造函数
    调用复制构造函数
    调用构造函数
    调用赋值构造函数
    调用析构函数
    调用析构函数
    调用析构函数
    展开全文
  • C++复制构造函数和拷贝构造函数

    千次阅读 2014-03-04 14:53:03
    拷贝构造函数参数的特点 赋值构造函数要申请内存。就像一般的构造函数一样。 而赋值操作,是已经申请好了内存。只是赋值。 对于一个类X,如果一个构造函数的第一个参数是下列之一: a) X& b) const X& c)...

    1 拷贝构造函数参数的特点

    赋值构造函数要申请内存。就像一般的构造函数一样。
    而赋值操作,是已经申请好了内存。只是赋值。


    对于一个类X,如果一个构造函数的第一个参数是下列之一:
    a) X&
    b) const X&
    c) volatile X&
    d) const volatile X&
    因此 X::X(X&, int=1); //是拷贝构造函数
    并且类中可以存在超过一个拷贝构造函数。拷贝构造函数采用引用作参数原因:
    1) 效率 。
    2) 避免死循环。 当一个对象需要以值方式传递时,编译器会生成代码调用它的拷贝构造函数以生成一个复本,因此当使用拷贝构造函数时会造成死循环。


    2 默认拷贝构造函数
    如果一个类中没有定义拷贝构造函数,那么编译器会自动产生一个默认的拷贝构造函数。这个默认的参数可能为X::X(const X&)或X::X(X&),由编译器根据上下文决定选择哪一个。默认拷贝构造函数的行为如下(递归的)(默认的构造函数X()、默认的拷贝赋值函数X& operator=(X& a) 被调用时行为同理):
    首先调用父类拷贝构造函数。然后拷贝构造函数对类中每一个数据成员执行成员拷贝的动作:
    a) 如果数据成员为某一个类的实例,那么调用此类的拷贝构造函数。
    b) 如果数据成员是一个数组(或指针、引用),对数组的每一个执行按位拷贝。
    c) 如果数据成员是一个数量,如int,double,那么调用系统内建的赋值运算符对其进行赋值。
    注:如果父类或成员的类提供的拷贝构造函数为private,则不能通过编译。这一点对默认的构造函数和默认的拷贝赋值函数被调用时同样适用,因此最好自己定义这三个函数和析构函数。


    3 拷贝构造函数调用时机
    以下情况都会调用拷贝构造函数:
    1) 一个对象以值传递的方式传入函数体。
    2) 一个对象以值传递的方式从函数返回。
    3) 一个对象需要通过另外一个对象进行初始化。

     

    4 理解copy constructor和copy assignment的一个例子
    class callwitch{
          string name ;
          static int objcount;
          public :
                 callwitch(const string& na = "") : name(na) {
                       objcount ++;
                       print("callwitch(const string&)");
                 };
                 ~callwitch(){
                       objcount --;
                       print("~callwitch()");   
                 }
                 callwitch(const callwitch& obj):name(obj.name) {
                       name = "copy of " + name;
                       objcount ++;
                       print("copy constructor");
                 };
                 callwitch& operator=(callwitch& obj){
                       print("copy assignment");
                 }
                 void print(const string& msg = "")const {
                      if(msg.size() !=0)
                          cout << msg << endl ;
                   cout << '/t' << name << ": " << "objcount = " << objcount << endl;
                 }
    };
    int callwitch::objcount = 0 ;

    callwitch f(callwitch obj)
    {
       cout << "returning from f()" << endl;
       return obj ;
    }
    int main(int argc, char *argv[])
    {
        callwitch c1("c1");
    callwitch c2 = c1 ; //copy constructor called。因为此时c2还未被初始化成为对象(即还未构造出来),无法调用copy assignment函数!
        callwitch c4 ;
        c4 = c1 ;               //copy assignment called
        c2.print("call f()");
        callwitch c3 = f(c1);
        cout << "call f(),no need return value" << endl;
        f(c1);
        system("PAUSE");
        return EXIT_SUCCESS;
    }
    以下是运行结果:
    callwitch(int)
            c1: objcount = 1
    copy constructor
            copy of c1: objcount = 2
    callwitch(int)
            : objcount = 3
    copy assignment
            : objcount = 3
    call f()
            copy of c1: objcount = 3
    copy constructor
            copy of c1: objcount = 4
    returning from f()
    copy constructor
            copy of copy of c1: objcount = 5
    ~callwitch()
            copy of c1: objcount = 4
    call f(),no need return value
    copy constructor
            copy of c1: objcount = 5
    returning from f()
    copy constructor
            copy of copy of c1: objcount = 6
    ~callwitch()
            copy of copy of c1: objcount = 5
    ~callwitch()
            copy of c1: objcount = 4


    5 其它:
    1)  最好自定义拷贝构造函数。如果使用编译器生成的拷贝构造函数,调用拷贝构造函数时实行位拷贝,当类内成员变量需要动态开辟堆内存时,执行classA obj1 ; classA obj2(obj1)。如果obj1中有一个成员变量指针已经申请了内存,那obj2中的那个成员变量也指向同一块内存。这就出现了问题:当obj1把内存释放后,obj2内的指针就是无效指针了,出现运行错误。
    2) 最好自定义operator=。如果打算在一个内含reference成员、内含const成员时,必须自己定义copy assignment操作符,因为C++本身不允许引用改指不同的对象,也不允许更改const成员;如果base class将copy assignment操作声明为private,编译器同样拒绝为其derived class生成一个copy assignment操作符(effective C++ Item 6)。


    1. 何时调用复制构造函数

        复制构造函数用于将一个对象复制到新创建的对象中。也就是说,它用于初始化过程中,而不是常规的赋值过程中。类的复制构造函数原型通常如下:

        class_name(const class_name&);

        它接受一个指向类对象的常量引用作为参数。例如,String类的复制构造函数的原型如下:

        String(const String&);

        新建一个对象并将其初始化为同类现有对象时,复制构造函数都将被调用。这在很多情况下都可能发生,最常见的情况是将新对象显示地初始化为现有的对象。例如,假设motto是一个String对象,则下面4种声明都将调用复制构造函数:

        String ditto(motto);

        String metoo = motto;

        String also = String(motto);

        String *pString = new String(motto);

        其中中间的2种声明可能会使用复制构造函数直接创建metto和also,也可能会使用复制构造函数生成一个临时对象,然后将临时对象的内容赋给metoo和also,这取决于具体的实现。最后一种声明使用motto初始化一个匿名对象,并将新对象的地址赋给pString指针。

        2. 何时调用赋值构造函数

        赋值构造函数是通过重载赋值操作符实现的,这种操作符的原型如下:

        Class_name& Class_name::operator=(const Class_name&);

        它接受并返回一个指向类对象的引用。例如,String 类的赋值操作符的原型如下:

        String& String::operator=(const String&);

        将已有的对象赋给另一个对象时,将使用重载的赋值操作符:

        String headline1("test");

        String knot;

        knot = headline1;

        初始化对象时,并不一定会使用赋值操作符:

        String metoo = knot;

        这里,metoo是一个新创建的对象,被初始化为knot的值,因此使用复制构造函数。不过,正如前面指出的,实现时也可能分两步来处理这条语句:使用复制构造函数创建一个临时对象,然后通过赋值将临时对象的值复制到新对象中。这就是说,初始化总是会调用复制构造函数,而使用=操作符时也可能调用赋值操作符


    #include <iostream>
    using namespace std;
    
    class Test
    {
    public:
    	Test();
    	~Test();
    	Test(const Test& t);
    	Test& operator=(const Test& t);
    
    private:
    	int t1;
    };
    
    Test::Test()
    {
    	cout<<"调用构造函数"<<endl;
    }
    
    Test::~Test()
    {
    	cout<<"调用析构函数"<<endl;
    }
    
    Test::Test(const Test& t)
    {
    	cout<<"调用复制构造函数"<<endl;
    }
    
    Test& Test::operator =(const Test& t)
    {
    	cout<<"调用赋值构造函数"<<endl;
    	t1 = t.t1;
    	return *this;
    }
    
    void main()
    {
    	Test t1;
    	Test t2 = t1;
    	Test t3;
    	t3 = t1;
    }

    输出如下:


    展开全文
  • 1. 何时调用复制构造函数 复制构造函数用于将一个对象复制到新创建的对象中。也就是说,它用于初始化过程中,而不是常规的赋值过程中。类的复制构造函数原型通常如下: class_name(const class_name&); 它接受一...

     1. 何时调用复制构造函数

        复制构造函数用于将一个对象复制到新创建的对象中。也就是说,它用于初始化过程中,而不是常规的赋值过程中。类的复制构造函数原型通常如下:

        class_name(const class_name&);

        它接受一个指向类对象的常量引用作为参数。例如,String类的复制构造函数的原型如下:

        String(const String&);

        新建一个对象并将其初始化为同类现有对象时,复制构造函数都将被调用。这在很多情况下都可能发生,最常见的情况是将新对象显示地初始化为现有的对象。例如,假设motto是一个String对象,则下面4种声明都将调用复制构造函数:

        String  ditto(motto);

        String  metoo = motto;

        String  also = String(motto);

        String  *pString = new String(motto);

        其中中间的2种声明可能会使用复制构造函数直接创建metto和also,也可能会使用复制构造函数生成一个临时对象,然后将临时对象的内容赋给metoo和also,这取决于具体的实现。最后一种声明使用motto初始化一个匿名对象,并将新对象的地址赋给pString指针。

    2. 何时调用赋值构造函数

        赋值构造函数是通过重载赋值操作符实现的,这种操作符的原型如下:

        Class_name& Class_name::operator=(const Class_name&);

        它接受并返回一个指向类对象的引用。例如,String 类的赋值操作符的原型如下:

        String& String::operator=(const String&);

        将已有的对象赋给另一个对象时,将使用重载的赋值操作符:

        String headline1("test");

        String knot;

        knot = headline1;

        初始化对象时,并不一定会使用赋值操作符:

        String metoo = knot;

        这里,metoo是一个新创建的对象,被初始化为knot的值,因此使用复制构造函数。不过,正如前面指出的,实现时也可能分两步来处理这条语句:使用复制构造函数创建一个临时对象,然后通过赋值将临时对象的值复制到新对象中。这就是说,初始化总是会调用复制构造函数,而使用=操作符时也可能调用赋值操作符

     

    实例代码如下:

    1. #include <iostream>
    2. using namespace std;
    3. class Test
    4. {
    5. public:
    6.     Test();
    7.     ~Test();
    8.     Test(const Test& t);
    9.     Test& operator=(const Test& t);
    10. private:
    11.     int t1;
    12. };
    13. Test::Test()
    14. {
    15.     cout<<"调用构造函数"<<endl;
    16. }
    17. Test::~Test()
    18. {
    19.     cout<<"调用析构函数"<<endl;
    20. }
    21. Test::Test(const Test& t)
    22. {
    23.     cout<<"调用复制构造函数"<<endl;
    24. }
    25. Test& Test::operator =(const Test& t)
    26. {
    27.     cout<<"调用赋值构造函数"<<endl;
    28.     t1 = t.t1;
    29.     return *this;
    30. }
    31. void main()
    32. {
    33.     Test t1;
    34.     Test t2 = t1;
    35.     Test t3;
    36.     t3 = t1;
    37. }

     

    输出如下:

     

    调用构造函数
    调用复制构造函数
    调用构造函数
    调用赋值构造函数
    调用析构函数
    调用析构函数
    调用析构函数

    展开全文
  • 对于我来说,在写代码的时候能用得上复制构造函数的机会并不多,不过这并不说明复制构造函数没什么用,其实复制构造函数能解决一些我们常常会忽略的问题。  为了说明复制构造函数作用,我先说说我们在编程时会...
    也许很多C++的初学者都知道什么是构造函数,但是对复制构造函数(copy constructor)却还很陌生。对于我来说,在写代码的时候能用得上复制构造函数的机会并不多,不过这并不说明复制构造函数没什么用,其实复制构造函数能解决一些我们常常会忽略的问题。
           为了说明复制构造函数作用,我先说说我们在编程时会遇到的一些问题。对于C++中的函数,我们应该很熟悉了,因为平常经常使用;对于类的对象,我们也很熟悉,因为我们也经常写各种各样的类,使用各种各样的对象;对于指针的操作,我们也不陌生吧?嗯,如果你还不了解上面三个概念的话,我想这篇文章不太适合你,不过看看也无碍^_^。我们经常使用函数,传递过各种各样的参数给函数,不过把对象(注意是对象,而不是对象的指针或对象的引用)当作参数传给函数的情况我们应该比较少遇见吧,而且这个对象的构造函数还涉及到一些内存分配的操作。嗯,这样会有什么问题呢?
           把参数传递给函数有三种方法,一种是值传递,一种是传地址,还有一种是传引用。前者与后两者不同的地方在于:当使用值传递的时候,会在函数里面生成传递参数的一个副本,这个副本的内容是按位从原始参数那里复制过来的,两者的内容是相同的。当原始参数是一个类的对象时,它也会产生一个对象的副本,不过在这里要注意。一般对象产生时都会触发构造函数的执行,但是在产生对象的副本时却不会这样,这时执行的是对象的复制构造函数。为什么会这样?嗯,一般的构造函数都是会完成一些成员属性初始化的工作,在对象传递给某一函数之前,对象的一些属性可能已经被改变了,如果在产生对象副本的时候再执行对象的构造函数,那么这个对象的属性又再恢复到原始状态,这并不是我们想要的。所以在产生对象副本的时候,构造函数不会被执行,被执行的是一个默认的构造函数。当函数执行完毕要返回的时候,对象副本会执行析构函数,如果你的析构函数是空的话,就不会发生什么问题,但一般的析构函数都是要完成一些清理工作,如释放指针所指向的内存空间。这时候问题就可能要出现了。假如你在构造函数里面为一个指针变量分配了内存,在析构函数里面释放分配给这个指针所指向的内存空间,那么在把对象传递给函数至函数结束返回这一过程会发生什么事情呢?首先有一个对象的副本产生了,这个副本也有一个指针,它和原始对象的指针是指向同块内存空间的。函数返回时,对象的析构函数被执行了,即释放了对象副本里面指针所指向的内存空间,但是这个内存空间对原始对象还是有用的啊,就程序本身而言,这是一个严重的错误。然而错误还没结束,当原始对象也被销毁的时候,析构函数再次执行,对同一块系统动态分配的内存空间释放两次是一个未知的操作,将会产生严重的错误。
           上面说的就是我们会遇到的问题。解决问题的方法是什么呢?首先我们想到的是不要以传值的方式来传递参数,我们可以用传地址或传引用。没错,这样的确可以避免上面的情况,而且在允许的情况下,传地址或传引用是最好的方法,但这并不适合所有的情况,有时我们不希望在函数里面的一些操作会影响到函数外部的变量。那要怎么办呢?可以利用复制构造函数来解决这一问题。复制构造函数就是在产生对象副本的时候执行的,我们可以定义自己的复制构造函数。在复制构造函数里面我们申请一个新的内存空间来保存构造函数里面的那个指针所指向的内容。这样在执行对象副本的析构函数时,释放的就是复制构造函数里面所申请的那个内存空间。
           除了将对象传递给函数时会存在以上问题,还有一种情况也会存在以上问题,就是当函数返回对象时,会产生一个临时对象,这个临时对象和对象的副本性质差不多。
    拷贝构造函数,经常被称作X(X&),是一种特殊的构造函数,他由编译器调用来完成一些基于同一类的其他对象的构件及初始化。它的唯一的一个参数(对象的引用)是不可变的(因为是const型的)。这个函数经常用在函数调用期间于用户定义类型的值传递及返回。拷贝构造函数要调用基类的拷贝构造函数和成员函数。如果可以的话,它将用常量方式调用,另外,也可以用非常量方式调用。 
    在C++中,下面三种对象需要拷贝的情况。因此,拷贝构造函数将会被调用。 
    1). 一个对象以值传递的方式传入函数体 
    2). 一个对象以值传递的方式从函数返回 
    3). 一个对象需要通过另外一个对象进行初始化 
    以上的情况需要拷贝构造函数的调用。如果在前两种情况不使用拷贝构造函数的时候,就会导致一个指针指向已经被删除的内存空间。对于第三种情况来说,初始化和赋值的不同含义是构造函数调用的原因。事实上,拷贝构造函数是由普通构造函数和赋值操作赋共同实现的。描述拷贝构造函数和赋值运算符的异同的参考资料有很多。 
    拷贝构造函数不可以改变它所引用的对象,其原因如下:当一个对象以传递值的方式传一个函数的时候,拷贝构造函数自动的被调用来生成函数中的对象。如果一个对象是被传入自己的拷贝构造函数,它的拷贝构造函数将会被调用来拷贝这个对象这样复制才可以传入它自己的拷贝构造函数,这会导致无限循环。 
    除了当对象传入函数的时候被隐式调用以外,拷贝构造函数在对象被函数返回的时候也同样的被调用。换句话说,你从函数返回得到的只是对象的一份拷贝。但是同样的,拷贝构造函数被正确的调用了,你不必担心。 
    如果在类中没有显式的声明一个拷贝构造函数,那么,编译器会私下里为你制定一个函数来进行对象之间的位拷贝(bitwise copy)。这个隐含的拷贝构造函数简单的关联了所有的类成员。许多作者都会提及这个默认的拷贝构造函数。注意到这个隐式的拷贝构造函数和显式声明的拷贝构造函数的不同在于对于成员的关联方式。显式声明的拷贝构造函数关联的只是被实例化的类成员的缺省构造函数除非另外一个构造函数在类初始化或者在构造列表的时候被调用。 
    拷贝构造函数是程序更加有效率,因为它不用再构造一个对象的时候改变构造函数的参数列表。设计拷贝构造函数是一个良好的风格,即使是编译系统提供的帮助你申请内存默认拷贝构造函数。事实上,默认拷贝构造函数可以应付许多情况。
    附另外一篇关于复制构造函数的文章:

    对一个简单变量的初始化方法是用一个常量或变量初始化另一个变量,例如:
      int m = 80;
      int n = m;
      我们已经会用构造函数初始化对象,那么我们能不能象简单变量的初始化一样,直接用一个对象来初始化另一个对象呢?答案是肯定的。我们以前面定义的Point类为例:
      Point pt1(15, 25);
      Point pt2 = pt1;
    后一个语句也可以写成:
      Point pt2( pt1);
    它是用pt1初始化pt2,此时,pt2各个成员的值与pt1各个成员的值相同,也就是说,pt1各个成员的值被复制到pt2相应的成员当中。在这个初始化过程当中,实际上调用了一个复制构造函数。当我们没有显式定义一个复制构造函数时,编译器会隐式定义一个缺省的复制构造函数,它是一个内联的、公有的成员,它具有下面的原型形式:
      Point:: Point (const Point &);
    可见,复制构造函数与构造函数的不同之处在于形参,前者的形参是Point对象的引用,其功能是将一个对象的每一个成员复制到另一个对象对应的成员当中。
      虽然没有必要,我们也可以为Point类显式定义一个复制构造函数:
      Point:: Point (const Point &pt)
      {
       xVal=pt. xVal;
       yVal=pt. yVal;
      } 
      如果一个类中有指针成员,使用缺省的复制构造函数初始化对象就会出现问题。为了说明存在的问题,我们假定对象A与对象B是相同的类,有一个指针成员,指向对象C。当用对象B初始化对象A时,缺省的复制构造函数将B中每一个成员的值复制到A的对应的成员当中,但并没有复制对象C。也就是说,对象A和对象B中的指针成员均指向对象C,实际上,我们希望对象C也被复制,得到C的对象副本D。否则,当对象A和B销毁时,会对对象C的内存区重复释放,而导致错误。为了使对象C也被复制,就必须显式定义复制构造函数。下面我们以string类为例说明,如何定义这个复制构造函数。

    例10-11
      class String
    {
     public:
      String(); //构造函数
      String(const String &s); //复制构造函数
      ~String(); //析构函数

      // 接口函数
      void set(char const *data);
      char const *get(void);

     private:
      char *str; //数据成员ptr指向分配的字符串
    };

    String ::String(const String &s)
    {
     str = new char[strlen(s.str) + 1];
     strcpy(str, s.str);
    }

    我们也常用无名对象初始化另一个对象,例如:
      Point pt = Point(10, 20);
      类名直接调用构造函数就生成了一个无名对象,上式用左边的无名对象初始化右边的pt对象。
      构造函数被调用通常发生在以下三种情况,第一种情况就是我们上面看到的:用一个对象初始化另一个对象时;第二种情况是当对象作函数参数,实参传给形参时;第三种情况是程序运行过程中创建其它临时对象时。下面我们再举一个例子,就第二种情况和第三种情况进行说明:
      Point foo(Point pt) 
      { 
       … 
       return pt;
      }
      void main()
      {
       Point pt1 = Point(10, 20);
       Point pt2;
       …
       pt2=foo(pt);
       …
      }
      在main函数中调用foo函数时,实参pt传给形参pt,将实参pt复制给形参pt,要调用复制构造函数,当函数foo返回时,要创建一个pt的临时对象,此时也要调用复制构造函数。

    缺省的复制构造函数
      在类的定义中,如果没有显式定义复制构造函数,C++编译器会自动地定义一个缺省的复制构造函数。下面是使用复制构造函数的一个例子:

    例10-12
      #include <iostream.h>
    #include <string.h>
    class withCC
    {
     public:
     withCC(){}
     withCC(const withCC&)
     {
      cout<<"withCC(withCC&)"<<endl;
     }
    };

    class woCC
    {
     enum{bsz = 100};
     char buf[bsz];
    public:
     woCC(const char* msg = 0)
     {
      memset(buf, 0, bsz);
      if(msg) strncpy(buf, msg, bsz);
     }
     void print(const char* msg = 0)const
     {
      if(msg) cout<<msg<<":";
      cout<<buf<<endl;
     }
    };

    class composite
    {
     withCC WITHCC;
     woCC WOCC;
    public:
     composite() : WOCC("composite()"){}
     void print(const char* msg = 0)
     {
      WOCC.print(msg);
     }
    };

    void main()
    {
     composite c;
     c.print("contents of c");
     cout<<"calling composite copy-constructor"<<endl;
     composite c2 = c;
     c2.print("contents of c2");
    }

      类withCC有一个复制构造函数,类woCC和类composite都没有显式定义复制构造函数。如果在类中没有显式定义复制构造函数,则编译器将自动地创建一个缺省的构造函数。不过在这种情况下,这个构造函数什么也不作。
      类composite既含有withCC类的成员对象又含有woCC类的成员对象,它使用无参的构造函数创建withCC类的对象WITHCC(注意内嵌的对象WOCC的初始化方法)。
      在main()函数中,语句:
      composite c2 = c;
    通过对象C初始化对象c2,缺省的复制构造函数被调用。
      最好的方法是创建自己的复制构造函数而不要指望编译器创建,这样就能保证程序在我们自己的控制之下。

    展开全文
  • 复制构造函数拷贝构造函数

    千次阅读 2014-09-16 11:39:03
    对于我来说,在写代码的时候能用得上复制构造函数的机会并不多,不过这并不说明复制构造函数没什么用,其实复制构造函数能解决一些我们常常会忽略的问题。  为了说明复制构造函数作用,我先说
  • 什么是复制构造函数复制构造函数是一种特殊的构造函数,具有一般构造函数的所有特性 ,它的形参是本类的对象的引用,比如(类名 对象名)。它的作用是使用一个已经存在的对象(此对象由复制构造函数的参数决定...
  • C++ primer的习题,被复制构造函数和赋值符的区别弄晕了。简单地说,有一道题目如下描述: class t1; class t2 = t1; 我先看见有一个等号,以为就是赋值符来做的,其实并不是这样的。做一个实验好了: [cpp]...
  • 假设Person是一个类,复制构造函数的调用会在以下几种情况下发生: 1、对象在创建时使用其他的对象初始化 Person p(q); //此时复制构造函数被用来创建实例p Person p = q; //此时复制构造函数被用来在定义...
  • 赋值运算符复制构造函数拷贝构造函数)  赋值运算符和复制构造函数都是用已存在的B对象来创建另一个对象A。不同之处在于:赋值运算符处理两个已有对象,即赋值前B应该是存在的;复制构造函数是生成一个全新的...
  • 拷贝构造函数是一种特殊的构造函数,用基于同一类的一个对象构造初始化另一个对象。当一个类的对象向该类的另一个对象赋值时,就会用到该类的赋值函数。拷贝构造函数是一个对象初始化一块内存区域,这块内存就是新...
  • 复制构造函数和赋值构造函数主要有以下两个区别: 1)复制构造是一个对象初始化一块内存区域,这块内存就是新对象的内存区; 例如: class A; A a; A b=a;//复制构造函数调用 A b(a);//复制构造函数调用 而...
  • 赋值运算符复制构造函数拷贝构造函数)易混处总结 赋值运算符和复制构造函数都是用已存在的B对象来创建另一个对象A。不同之处在于:赋值运算符处理两个已有对象,即赋值前B应该是存在的;复制构造函数是...
  • 拷贝构造函数和拷贝赋值函数

    千次阅读 2014-07-09 13:54:06
    拷贝构造函数和拷贝赋值hanshu
  • 每个类只有一个析构函数,但可以有多个构造函数(包含一个拷贝构造函数,其他的为普通构造函数)和多个赋值...默认的拷贝构造函数和默认的赋值构造函数均采用“按成员拷贝”默认方式来实现。但是,基本类型变量(包括
  • 构造函数与拷贝构造函数

    千次阅读 多人点赞 2019-04-03 09:07:15
    拷贝构造函数和构造函数不能分开说,他们都是初始化对象的一种方法。但是我们这里用构造函数辅助说明拷贝构造函数,主要说说拷贝构造函数的声明,用途和使用注意事项。 众所周知,构造函数是一个初始化类对象的函数...
  • C++中一般创建对象,拷贝或赋值的方式有构造函数,拷贝构造函数,赋值函数这三种方法。下面就详细比较下三者之间的区别以及它们的具体实现 ...默认构造函数和拷贝构造函数 析构函数 赋值函数(...
  • 拷贝构造函数和重载赋值运算符设为private来禁止拷贝
  • 什么时候需要拷贝构造函数和赋值构造函数? 每个C++类只有一个析构函数,但可以有多个构造函数和多个赋值函数。其中构造函数包括默认构造函数(无参,或参数全有默认值),拷贝构造函数。在编程时,如果程序员不...
  • 赋值构造函数和拷贝构造函数的区别 复制构造函数 《c++ Primer Plus(第五版)中文版》中 第385页中写道: 假设motto是一个StringBad对象,则下面4中声明都将是调用复制构造函数(及拷贝构造函数)...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 98,728
精华内容 39,491
关键字:

复制构造函数和拷贝构造函数