Delete 关键字新特性
在C ++ 11中,引入了关键字delete的新功能。我们可以将delete关键字应用于限制函数的使用。
下文将演示以下常见的使用场景:
- 应用于编译器自动生成的函数以禁止使用特定的操作(如复制,比较)
- 应用在成员函数上防止数据类型转换时导致数据丢失
- 应用在new运算符上来限制堆上对象的创建
- 应用在模板类上来限制创建特定的类实例
禁用复制构造函数和赋值运算符
我们可以将delete应用于编译器自动生成的函数,也可以用于其他函数。下面的User类中删除了复制构造函数和赋值运算符,如果有人尝试调用已删除的函数,则它将生成编译时错误。
class User{
int id;
string name;
public:
User(int userId, std::string userName) : id(userId), name(userName){}
User(const User & obj) = delete; //禁用复制构造函数
User & operator = (const User & obj) = delete; //禁用赋值运算符
};
下面的代码尝试使用赋值运算符,因此引发了编译错误:'User::User(const User &)' : attempting to reference a deleted
。
int main(){
User userObj(1, "Driver");
User obj = userObj;
return 0;
}
防止自动类型转换造成数据丢失
在上面的例子中,虽然User构造函数接受int作为id的参数类型,但是我们依然可以传入double。编译时不会报错:
User userObj2(2.1, "Double");
使用delete关键字,我们可以防止参数传入时发生的自动类型转换:
User(double userId, std::string userName) = delete;
在使用delete关键字后,使用double创建User对象会抛出编译时错误:User::User(double,std::string)' : attempting to reference a deleted function
限制动态创建对象
可以将delete 关键字用在new运算符,从而限制动态创建User对象。
class User{
int id;
string name;
public:
User(int userId, std::string userName) : id(userId), name(userName){}
//禁止使用new运算符在堆上创建对象
void * operator new (size_t) = delete;
};
new运算符被禁止使用后,以下代码将会产生编译时错误:'void *User::operator new(size_t)' : attempting to reference a deleted function
auto user1 = new User(1, "Driver");
限制模板类创建特定类型的实例
使用delete关键字,我们可以限制模板类或模板函数的某些实例化。让我们看看如何做到这一点,
将上面的User类改造成模板类:
template <typename T>
class User{
T id;
string wigth;
public:
User(T a, T b) : x(a), y(b){}
User(char a, char b) = delete;
};
现在,假设我们要限制没有人可以使用带有char作为模板参数的User类。为此,我们需要使用通过delete关键字:
User(char a, char b) = delete;
此后,尝试使用char作为模板参数的类将生成编译时错误。'User<std::string>::User(char,char)' : attempting to reference a deleted function
User<string> user2('1', '0');