写了又删,删了又写,才发现这一章节不好描述。

 

那就假定个前提吧,假定已经知道:

① C++的类有构造函数。

② 如果不提供任何构造函数,那编译器会生成默认的无参构造函数--默认构造函数只会进行成员变量的初始化。

③ 如果提供了任何一个构造函数,那编译器就不会再生成默认的无参构造函数。

④ 函数的形参都是实参的副本(引用类型除外)。

⑤ 构造函数也是函数。

⑥ 直接初始化是在括号()中,复制初始化则使用=赋值操作符---注意,是定义不是赋值

针对⑥,Person p2=p1;这是复制初始化! p2=p3;这才是赋值!!!

在此基础上,稍作推理

一、如果构造函数是单形参、且形参类型为该类的类型的构造函数:

  以 class Person 为例,

string name="anonymous";
int age=18;
Person p1(name, age);
Person p2(p1); //note this

  根据上面前提的④,p2 需要 p1 的一个副本(复制一个),这时就出现问题了:该怎么复制

  这就是复制构造函数的作用了--用于指明如何复制。

  再推理一下,如果不能使用副本,那还能使用什么?必须是引用啊(不要说指针,囧)!所以复制构造函数就是单形参、且形参类型为该类类型的引用 (常const修饰)的构造函数。

class Person{
    public:
        Person(const Person&); //copy-constructor
        ....
};

  需要说明的是,编译器会自动生成一个默认的复制构造函数,原则就是一一复制成员变量。这里面又存在一个问题,如果存在指针类型的成员变量,那么与其他成员变量不同的是,复制后的指针仍然指向同一个地址!这可能会导致很严重的bug。如下:

#include <iostream>
#include <string>

using namespace std;

//注意,有指针成员,但没有自定义复制构造函数。
//这时,其他成员复制时都是副本,而指针成员却指向同一个地址。
class HasPtr{
private:
    int *ptr;
    int val;

public:
    HasPtr(int *p, int i):ptr(p), val(i){}

    int *get_ptr() const { return ptr; }
    void set_ptr(int *p){ ptr=p; }

    int get_int() const { return val; }
    void set_int(int i){ val=i; }
    
    int get_ptr_val() const { return *ptr; }
    void set_ptr_val(int i) const { *ptr = i; } //why not take a ref?
};

int main(){
    int obj=10;

    HasPtr ptr1(&obj, 42);
    HasPtr ptr2(ptr1); // copy-constructor

    cout<<ptr1.get_ptr()<<"--"<<ptr1.get_ptr_val()<<endl;
    cout<<ptr2.get_ptr()<<"--"<<ptr2.get_ptr_val()<<endl;

    ptr1.set_int(3);
    ptr2.set_int(5);

    cout<<ptr1.get_int()<<"--"<<ptr2.get_int()<<endl;

    ptr1.set_ptr_val(7);
    cout<<ptr1.get_ptr()<<"--"<<ptr1.get_ptr_val()<<endl;
    cout<<ptr2.get_ptr()<<"--"<<ptr2.get_ptr_val()<<endl;

    cout<<"-----------"<<endl;

    int *ip=new int(42);
    HasPtr ptr(ip, 2);
    delete ip;
    ptr.set_ptr_val(3);//OOPS! error
    

    return 0;
}
View Code

相关文章:

  • 2022-02-15
  • 2022-12-23
  • 2022-12-23
  • 2021-07-03
  • 2022-12-23
  • 2021-08-05
  • 2022-12-23
猜你喜欢
  • 2021-10-17
  • 2022-12-23
  • 2022-12-23
  • 2021-07-08
  • 2021-11-10
相关资源
相似解决方案