《深入理解C++11》笔记-默认函数的控制

上一篇:《深入理解C++11》笔记-指针空指nullptr

在C++中声明自定义的类之后,编译器会默认生成一些成员函数,这些函数被称为默认函数。包括构造函数、拷贝构造函数、拷贝赋值构造函数、移动构造函数、移动拷贝函数、析构函数。另外,编译器还会默认生成一些操作符函数,包括operator ,、operator &、operator &&、operator 、operator ->、operator ->、operator new、operator delete。

显式缺省函数 (= default)

但是如果实现了这些函数的自定义版本后,编译器就不会去生成默认的版本。有时候我们需要声明带参数的构造函数,此时就不会生成默认的构造函数,这样会导致类不再是POD类型(详见https://blog.csdn.net/WizardtoH/article/details/80767740),从而影响类的优化:

class Example {
public:
    Example(int i) : data(i) {}

private:
    int data;
};

int main()
{
    std::cout << std::is_pod <Example>::value << std::endl;  // 0

    return 0;
}

C++11中提供了新的机制来控制默认函数生成来避免这个问题,我们在声明时在函数末尾加上”= default”来显式地指示编译器去生成该函数的默认版本,这样就保证了类还是POD类型:

class Example {
public:
    Example() = default;
    Example(int i) : data(i) {}

private:
    int data;
};

int main()
{
    std::cout << std::is_pod <Example>::value << std::endl;  // 1

    return 0;
}

显式删除函数 (= delete)

另一方面,有时候可能需要限制一些默认函数的生成,例如需要禁止拷贝构造函数的使用。原来,通过把拷贝构造函数声明为private成员,这样一旦使用编译器就会报错。而在C++11中,在韩式的定义或者声明后面加上”= delete”就能实现这个效果:

class Example {
public:
    Example() = default;
    Example(const Example& ex) = delete;

private:
    int data;
};

int main()
{
    Example ex;
    Example ex1(ex);   // 编译失败

    return 0;
}

其他用法

= default和= delete 能够更加精准的控制类的默认函数版本。其中,= default同样也能在类外的定义中修饰成员函数:

class Example {
public:
    Example() = default;
    Example(const Example&);

private:
    int data;
};

Example::Example(const Example& ex) = default;

这样的好处是,能够为一个类实现多个版本,只要我们在头文件里声明同样的函数,而在不同的cpp文件中用不同的方法实现,当选择不同的cpp编译时产生的版本就不同。

关于= delete,它不仅局限于限制生成默认函数,还能避免编译器做一些不必要的隐式数据转换:

class Example {
public:
    Example(int i) {}
};


int main()
{
    Example ex(1);
    Example ex1('a');     // 编译成功,char会隐式装换成int型

    return 0;
}

有时候我们不想要这种隐式转换:

class Example {
public:
    Example(int i) {}
    Example(char c) = delete;
};


int main()
{
    Example ex(1);
    Example ex1('a');  // 编译失败

    return 0;
}

这个方法也能用于普通函数:

void func(int i) {}
void func(char c) = delete;

int main()
{
    func(1);
    func('a');   // 编译失败

    return 0;
}

另外,还有很多用法,例如显示删除new操作符来避免在堆上分配对象、显示删除析构函数用于构建单例模式等等。

下一篇:《深入理解C++11》笔记-lambda函数

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值