C++构造函数的default和delete

简介: 转自:https://blog.csdn.net/u010591680/article/details/71101737 C++11中,当类中含有不能默认初始化的成员变量时,可以禁止默认构造函数的生成,myCl...

转自:https://blog.csdn.net/u010591680/article/details/71101737

 

C++11中,当类中含有不能默认初始化的成员变量时,可以禁止默认构造函数的生成,

myClass()=delete;//表示删除默认构造函数

myClass()=default;//表示默认存在构造函数

当类中含有不能默认拷贝成员变量时,可以禁止默认构造函数的生成,

myClass(const myClass&)=delete;//表示删除默认拷贝构造函数,即不能进行默认拷贝

myClass & operatir=(const myClass&)=delete;//表示删除默认拷贝构造函数,即不能进行默认拷贝
——————————————————————————————————————————————————————

 

转自:https://blog.csdn.net/u012333003/article/details/25299939

 

同时C++规定,一旦程序员实现了这些函数的自定义版本,则编译器不会再自动生产默认版本。注意只是不自动生成默认版本,当然还是可手动生成默认版本的。当我们自己定义了待参数的构造函数时,我们最好是声明不带参数的版本以完成无参的变量初始化,此时编译是不会再自动提供默认的无参版本了。我们可以通过使用关键字default来控制默认构造函数的生成,显式地指示编译器生成该函数的默认版本。比如:
 

class MyClass
{
  public:
    MyClass()=default;  //同时提供默认版本和带参版本,类型是POD的
    MyClass(int i):data(i){}
  private:
    int data;
};

有些时候我们希望限制默认函数的生成。典型的是禁止使用拷贝构造函数,以往的做法是将拷贝构造函数声明为private的并不提供实现,这样当拷贝构造对象时编译不能通过,C++11则使用delete关键字显式指示编译器不生成函数的默认版本。比如:

class MyClass
{
  public:
     MyClass()=default;
     MyClass(const MyClass& )=delete;
  ......
}

当然,一旦函数被delete过了,那么重载该函数也是非法的,该函数我们习惯上称为删除函数。

 

二、default和delete的其他用途

  上面我们已经看到在类中我们可用default和delete修饰成员函数,使之成为缺省函数或者删除函数,在类的外面,也可以在类定义之外修饰成员函数,比如:

class MyClass
{
  public:
    MyClass()=default;
    MyClass() &operator=(const MyClass& );
);
//在类的定义外用default来指明缺省函数版本
inline MyClass& MyClass::operator=(const MyClass& )=default;

而关于delete的显式删除,并非局限于成员函数,由此我们也知default是只局限作用于类的部分成员函数的。于是我们还可用delete来避免不必要的隐式数据类型转换。比如:

class MyClass
{
  public:
    MyClass(int i){};
    MyClsss(char c)=delete;  //删除char版本的构造函数
};
void Fun(MyClass m){}
int main()
{
  Func(3);
  Func('a');  //编译不能通过
  MyClass m1(3);
  MyClass m2('a');  //编译不能通过
}

这是因为char版本的构造函数被删除后,试图从char构造MyClass对象的方式是不允许的了。但去掉这句的函数删除后,编译器会隐式的将a转换为整型使得编译通过,调用的是整型构造函数,这可能并不是你所想要的。但是如果这样:

class MyClass
{
  public:
    MyClass(int i){};
    explicit MyClsss(char c)=delete;  //删除explicit的char版本的构造函数
};
void Fun(MyClass m){}
int main()
{
  Func(3);
  Func('a');  //编译可通过
  MyClass m1(3);
  MyClass m2('a');  //编译不能通过
}

将构造函数explicit后,构造函数一样的还是不能发生char的构造,因为char构造版本被删除了,但在Func的调用用,编译器会尝试将c转换为int,即Func(\\a')会调用一次MyClass(int )构造,顺利通过编译。于是我们不提倡explicit和delete混用。

对与普通函数delete也有类型的效果。比如:

void Func(int i){};
void Func(char c)=delete;  //显式删除char版本
int main()
{
  Func(3);
  Func('c);  //无法编译通过
  return 0;
}

这里因为Func的char版本已经被删除,故Func('c')会编译失败。

delete的有趣的用法还有删除operator new操作符,编码在堆上分配该类的对象如:

void* operator new(std::size_t)=delete;

另外析构函数也是可以delete的

这样做的目的是我们在指定内存位置进行内存分配时并不需要析构函数来完成对象级别的清理,这时我们可显示删除析构函数来限制自定义类型在栈上或者静态的构造。

 

相关文章
|
1月前
|
C++
【C++】深入解析C/C++内存管理:new与delete的使用及原理(二)
【C++】深入解析C/C++内存管理:new与delete的使用及原理
|
1月前
|
编译器 C++ 开发者
【C++】深入解析C/C++内存管理:new与delete的使用及原理(三)
【C++】深入解析C/C++内存管理:new与delete的使用及原理
|
1月前
|
存储 C语言 C++
【C++】深入解析C/C++内存管理:new与delete的使用及原理(一)
【C++】深入解析C/C++内存管理:new与delete的使用及原理
|
4天前
|
存储 编译器 C++
【c++】类和对象(下)(取地址运算符重载、深究构造函数、类型转换、static修饰成员、友元、内部类、匿名对象)
本文介绍了C++中类和对象的高级特性,包括取地址运算符重载、构造函数的初始化列表、类型转换、static修饰成员、友元、内部类及匿名对象等内容。文章详细解释了每个概念的使用方法和注意事项,帮助读者深入了解C++面向对象编程的核心机制。
24 5
|
10天前
|
存储 编译器 C++
【c++】类和对象(中)(构造函数、析构函数、拷贝构造、赋值重载)
本文深入探讨了C++类的默认成员函数,包括构造函数、析构函数、拷贝构造函数和赋值重载。构造函数用于对象的初始化,析构函数用于对象销毁时的资源清理,拷贝构造函数用于对象的拷贝,赋值重载用于已存在对象的赋值。文章详细介绍了每个函数的特点、使用方法及注意事项,并提供了代码示例。这些默认成员函数确保了资源的正确管理和对象状态的维护。
39 4
|
2月前
|
编译器 C++
C++ 类构造函数初始化列表
构造函数初始化列表以一个冒号开始,接着是以逗号分隔的数据成员列表,每个数据成员后面跟一个放在括号中的初始化式。
73 30
|
1月前
|
程序员 C语言 C++
C++入门5——C/C++动态内存管理(new与delete)
C++入门5——C/C++动态内存管理(new与delete)
68 1
|
1月前
|
编译器 C语言 C++
C++入门4——类与对象3-1(构造函数的类型转换和友元详解)
C++入门4——类与对象3-1(构造函数的类型转换和友元详解)
20 1
|
1月前
|
C++
C++构造函数初始化类对象
C++构造函数初始化类对象
21 0
|
1月前
|
C++
C++入门4——类与对象3-2(构造函数的类型转换和友元详解)
C++入门4——类与对象3-2(构造函数的类型转换和友元详解)
21 0