C++11 delete和default
Defaulted 函数
C++ 的类有四个特殊成员函数,它们分别是:默认构造函数、析构函数、拷贝构造函数以及拷贝赋值运算符。这些类的特殊成员函数负责创建、初始化、销毁,或者拷贝类的对象。
如果程序员没有显式地为一个类定义某个特殊成员函数,而又需要用到该特殊成员函数时,则编译器会隐式的为这个类生成一个默认的特殊成员函数。但是,如果程序员为类显式的自定义了非默认构造函数,编译器将不再会为它隐式的生成默认构造函数,手动编写的特殊成员函数的代码执行效率比编译器自动生成的特殊成员函数低。
先看一个示例程序 :
class X{
public:
X(){}; // 手动定义默认构造函数
X(int i){
a = i;
}
private:
int a;
};
X x; // 正确,默认构造函数 X::X() 存在
从以上例子可以看出,原本期望编译器自动生成的默认构造函数需要程序员手动编写了,即程序员的工作量加大了。此外,手动编写的默认构造函数的代码执行效率比编译器自动生成的默认构造函数低。
Defaulted 函数的提出
为了解决上面例子提出的两个问题:
1. 减轻程序员的编程工作量;
2. 获得编译器自动生成的默认特殊成员函数的高的代码执行效率;
C++11 标准引入了一个新特性:defaulted 函数。程序员只需在函数声明后加上“=default;”,就可将该函数声明为 defaulted 函数,编译器将为显式声明的 defaulted 函数自动生成函数体。
例如:
class X{
public:
X()= default;
X(int i){
a = i;
}
private:
int a;
};
X x;
在上列代码中,编译器会自动生成默认构造函数 X::X(){},该函数可以比用户自己定义的默认构造函数获得更高的代码效率。
Defaulted 函数的用法及示例
Defaulted 函数特性仅适用于类的特殊成员函数,且该特殊成员函数没有默认参数。
Defaulted 函数既可以在类体里(inline)定义,也可以在类体外(out-of-line)定义。
例如:
class X{
public:
X() = default; //Inline defaulted 默认构造函数
X(const X&);
X& operator = (const X&);
~X() = default; //Inline defaulted 析构函数
};
X::X(const X&) = default; //Out-of-line defaulted 拷贝构造函数
X& X::operator = (const X&) = default; //Out-of-line defaulted 拷贝赋值操作符
在 C++ 代码编译过程中,如果程序员没有为类 X 定义析构函数,但是在销毁类 X 对象的时候又需要调用类 X 的析构函数时,编译器会自动隐式的为该类生成一个析构函数。该自动生成的析构函数没有参数,包含一个空的函数体,即 X::~X(){ }。
Deleted 函数
对于 C++ 的类,如果程序员没有为其定义特殊成员函数,那么在需要用到某个特殊成员函数的时候,编译器会隐式的自动生成一个默认的特殊成员函数,比如拷贝构造函数,或者拷贝赋值操作符。
例如:
class X{
public:
X();
};
int main(){
X x1;
X x2=x1; // 正确,调用编译器隐式生成的默认拷贝构造函数
X x3;
x3=x1; // 正确,调用编译器隐式生成的默认拷贝赋值操作符
}
在上面代码中,程序员不需要自己手动编写拷贝构造函数以及拷贝赋值操作符,依靠编译器自动生成的默认拷贝构造函数以及拷贝赋值操作符就可以实现类对象的拷贝和赋值。这在某些情况下是非常方便省事的,但是在某些情况下,假设我们不允许发生类对象之间的拷贝和赋值,可是又无法阻止编译器隐式自动生成默认的拷贝构造函数以及拷贝赋值操作符,那这就成为一个问题了。
Deleted 函数的提出
为了能够让程序员显式的禁用某个函数,C++11 标准引入了一个新特性:deleted 函数。程序员只需在函数声明后加上“=delete;”,就可将该函数禁用。
例如,我们可以将类 X 的拷贝构造函数以及拷贝赋值操作符声明为 deleted 函数,就可以禁止类 X 对象之间的拷贝和赋值。
class X{
public:
X();
X(const X&) = delete; // 声明拷贝构造函数为 deleted 函数
X& operator = (const X &) = delete; // 声明拷贝赋值操作符为 deleted 函数
};
int main(){
X x1;
X x2=x1; // 错误,拷贝构造函数被禁用
X x3;
x3=x1; // 错误,拷贝赋值操作符被禁用
}
在上面代码中,虽然只显式的禁用了一个拷贝构造函数和一个拷贝赋值操作符,但是由于编译器检测到类 X 存在用户自定义的拷贝构造函数和拷贝赋值操作符的声明,所以不会再隐式的生成其它参数类型的拷贝构造函数或拷贝赋值操作符,也就相当于类 X 没有任何拷贝构造函数和拷贝赋值操作符,所以对象间的拷贝和赋值被完全禁止了。
Deleted 函数的用法及示例
defaulted函数特性规定了只有类的特殊成员函数才能被声明为 defaulted 函数,但是 deleted 函数特性并没有此限制。类的成员函数,非成员函数,即普通函数也可以被声明为 deleted 函数。
必须在函数第一次声明的时候将其声明为 deleted 函数,否则编译器会报错。即对于类的成员函数而言,deleted 函数必须在类体里(inline)定义,而不能在类体外(out-of-line)定义。
Deleted 函数特性还可用于禁用类的某些转换构造函数,从而避免不期望的类型转换。在清单 12 中,假设类 X 只支持参数为双精度浮点数 double 类型的转换构造函数,而不支持参数为整数 int 类型的转换构造函数,则可以将参数为 int 类型的转换构造函数声明为 deleted 函数。
#include <cstddef>
using namespace std; class X
{
public:
X(int) = delete;
X(double);
X() = default; int add(int a, int b) = delete;
double add(double a, double b) {
return a + b;
} void show() = delete; void *operator new(size_t) = delete;
void *operator new[](size_t) = delete;
}; int main()
{
//X *pa = new X(1); //错误,操作符被禁用
//X *pb = new X[10]; //错误,操作符被禁用
X x;
//x.add(1, 4); //错误,已被禁止
x.add(1.0, 4.0); return ;
}
值得一提的是,在上述示例中,虽然 add(int, int)函数被禁用了,但是禁用的仅是函数的定义,即该函数不能被调用。但是函数标示符 add 仍是有效的,在名字查找和函数重载解析时仍会查找到该函数标示符。
如果编译器在解析重载函数时,解析结果为 deleted 函数,则会出现编译错误。
C++11 delete和default的更多相关文章
- 拷贝构造函数,深拷贝,大约delete和default相关业务,explicit,给定初始类,构造函数和析构函数,成员函数和内联函数,关于记忆储存,默认参数,静态功能和正常功能,const功能,朋友
1.拷贝构造 //拷贝构造的规则,有两种方式实现初始化. //1.一个是通过在后面:a(x),b(y)的方式实现初始化. //2.另外一种初始化的方式是直接在构造方法里面实现初始化. 案比例如以 ...
- C++11 之 delete 和 default
1 特殊成员函数 设计一个类,没有成员函数 (member function),只有数据成员 (member data) class DataOnly { private: std::string ...
- c++11 delete禁用函数
c++11添加了delete关键字. 不想用那个函数,在那个函数后面加 = delete就可以了: 比如: 在函数重载中,可用 delete 来滤掉一些函数的形参类型,如下: bool IsLucky ...
- =delete(c++11)
1.为什么要阻止类对象的拷贝? 1)有些类,不需要拷贝和赋值运算符,如:IO类,以避免多个拷贝对象写入或读取相同的IO缓冲 2.如何阻止? 1)不定义拷贝构造函数和拷贝赋值运算符时,好心的编译器也会及 ...
- c++11新特性(了解)
从C++出来到现在已经13年了. Bjarne Stroustrup(C++的创造者)最近评价C++:”感觉像个新的语言“. 事实上,C++11核心已经发生了很重大的变化: . 支持Lambda表达式 ...
- C++ 11 之学习总结
感慨时间过的好快,C++ 11出来都5年了,现在才开始学习,但为时也不晚: 主要是网上及身边的朋友大肆宣扬C++ 11的某些优化,弄得别人心里痒痒的,所以就花了3天学习了点基本知识,相对于整个C++ ...
- 【M4】非必要不提供default 构造方法
1.default 构造方法意味着,没有外来信息的情况下,进行初始化,构造出一个对象.对于有些对象是很合理的,比如数值之类的对象,可以初始化为0:对于指针之类的对象,初始化为null:对于集合如vec ...
- C++11 in Qt5
本文转载自:http://woboq.com/blog/cpp11-in-qt5.html C++11 in Qt5 Posted by Olivier Goffart on 11 June 20 ...
- C++11 中值得关注的几大变化(网摘)
C++11 中值得关注的几大变化(详解) 原文出处:[陈皓 coolshell] 源文章来自前C++标准委员会的 Danny Kalev 的 The Biggest Changes in C++11 ...
随机推荐
- ORA-01034: ORACLE not available解决
问题现象: alter user scott account unlock; ERROR at line 1:ORA-01034: ORACLE not availableProcess ID: 0S ...
- 解决PHP Fatal error mysql_connect() mysql_query()的问题
单独安装Apache.PHP.Mysql在进行开发调试的时候经常会遇到各种问题,好多人说比appserv或者xampp集成安装包麻烦,其实不然,单独配置可以更深入的了解每个部件分别是怎么运行的,深入理 ...
- Huginn部署到 Heroku
折腾了几个小时,现在记录下安装步骤 1.本机Win10,放弃本地安装,官网建议也是, 2.安装虚拟机,装ubuntu系统 3.更换国内源(包括apt和gem,bunlde)ruby中国 4.注册her ...
- Scribes:小型文本编辑器,支持远程编辑
Scribes是一款简洁的文本编辑器.现在给大家介绍下. 功能列表, Python插件扩展 支持远程编辑(如ftp, sftp, ssh, samba, webdav, webdavs) ...
- linux下淘宝安全控件问题
2009-09-21 我的环境:ubuntu9.04 firefox3.0.14 下载压缩包http://blog.alipay.com/wp-content/2008/10/aliedit.t ...
- Android开发环境——SDK相关内容汇总
Android开发环境将分为SDK相关内容.Eclipse ADT相关内容.模拟器AVD相关内容.调试器DDMS相关内容.日志LogCat相关内容.连接驱动ADB相关内容.内存泄露检测工具MAT相关 ...
- react.js 测试
<html> <head> <title>hellow</title> <script src="ht ...
- k8s实战之Service
一.概述 为了适应快速的业务需求,微服务架构已经逐渐成为主流,微服务架构的应用需要有非常好的服务编排支持,k8s中的核心要素Service便提供了一套简化的服务代理和发现机制,天然适应微服务架构,任何 ...
- MongoDB学习笔记(11)-- Index
索引通常能够极大的提高查询的效率,如果没有索引,MongoDB在读取数据时必须扫描集合中的每个文件并选取那些符合查询条件的记录. 这种扫描全集合的查询效率是非常低的,特别在处理大量的数据时,查询可以要 ...
- top 学习
通常top命令是会持续运行而不终止的. 要在脚本里用,需要添加一些选项参数,尤其是-b.例如:top -b -n 2 -d 3 >/tmp/log -b表示批处理模式(Batch mode),以 ...