一直对C++拷贝构造函数和赋值函数有所混淆,索性今天自己也整理篇这方面的文章,一遍加深记忆
首先把C++里面分为五类函数
下面就以上面的图进行说明
普通构造函数分为两类,无参构造函数,又参数构造函数
格式:
class MyClass {
public:
MyClass()
};
特点:
MyClass::MyClass() {
//添加你自己初始化的东西
}
class MyClass {
public:
MyClass(int val);
private:
int val;
};
特点:
有参构造函数一般用在在构造函数的时候需要用已知的参数进行初始化的地方,比如我需要用一个int类型的值10来初始化一个对象,可以写成
MyClass *myClass = new MyClass(10);
首先构造函数,一定是从无到有的一个创造的过程,意思就是我需要创建一个对象myClass,这个对象之前不存在,我需要另外一个对象other来给到一些信息来才能创建。
MyClass (const MyClass&other)
MyClass *my1;
MyClass *my2 = new MyClass;
my1 = my2; //调用了拷贝构造函数
在C++中,3种对象需要复制,此时拷贝构造函数会被调用
1)如果用户没有自定义拷贝构造函数,并且在代码中使用到了拷贝构造函数,编译器就会生成默认的拷贝构造函数。但如果用户定义了拷贝构造函数,编译器就不在生成。
2)如果用户定义了一个构造函数,但不是拷贝构造函数,而此时代码中又用到了拷贝构造函数,那编译器也会生成默认的拷贝构造函数。
我们可以想象如果在other对象里我们malloc 了一片内存,然后对这片内存进行赋值操作,如果浅copy操作,那么myClass里面只是保存了other对象里的地址,两个人时共享这个地址,这往往并不是我们想要的,因此我们就需要深copy,深copy的操作就是自己在copy构造函数的时候分配自己的内存,然后把other里面的内存上面的数据copy到myClass上来,完成用other的参数初始化了myClass的参数。
有人把赋值函数也理解成为一种构造函数,我一般不这样理解。赋值函数的前提是对象已经存在,我还需要用一个对象去更改,去赋值,才会调用赋值函数,他不满足一个对象从无到有的过程,所以他不能理解为一个构造函数。
格式:
MyClass & operator = (const MyClass& other);
赋值函数的例子
MyClass *my1 = new MyClass;
MyClass *my2 = new MyClass;
my1 = my2; //调用了赋值函数
析构函数一般主要目的是把自己所拥有的资源归还给系统,对象声明周期终止。
~MyClass();
我们可以看到很多开源的代码里面类都继承了noncopyable,
我这里尝试理解了这种写法的作用,主要是为了限制他的使用范围
举个例子
class MyClass : public noncopyable {
};
MyClass *myClass = new MyClass;
有一下几点限制,否则会出现编译错误
class noncopyable的基本思想是把构造函数和析构函数设置protected权限,这样子类可以调用,但是外面的类不能调用,那么当子类需要定义构造函数的时候不至于通不过编译。但是最关键的是noncopyable把拷贝构造函数和拷贝赋值函数做成了private的,继承自noncopyable的类在执行拷贝操作时会调用基类的拷贝操作,但是基类的拷贝操作是private的,因此无法调用,引发编译错误。
class noncopyable {
protected:
noncopyable() = default;
~noncopyable() = default;
private:
noncopyable(const noncopyable&) = delete;
const noncopyable& operator=( const noncopyable& ) = delete;
};
所谓移动语义,指的就是以移动而非深拷贝的方式初始化含有指针成员的类对象。简单的理解,移动语义指的就是将其他对象(通常是临时对象)拥有的内存资源“移为已用”。
由于时间有限 这里不做过多的解释,在网上摘抄了一段String实现的代码,自己测试和体会。
#include
#include
#include
#include
using namespace std;
class String{
public:
char *str;
String(char value[])
{
cout<<"普通构造函数..."< vs;
vs.push_back(move(s));
//vs.push_back(s);
cout<
编译方式:
g++ -o String String.cpp -std=c++11