首页 > 其他 > 详细

复制控制

时间:2016-02-23 20:48:35      阅读:275      评论:0      收藏:0      [点我收藏+]

每种类型还定义了创建该类型的对象时会发生什么——构造函数定义了该类类型对象的初始化。类型还能控制复制、赋值或撤销该类型的对象时会发生什么——类通过特殊的成员函数:复制构造函数、赋值操作符和析构函数来控制这些行为

复制构造函数是一种特殊构造函数,具有单个形参,该形参(常用 const 修饰)是对该类类型的引用。当定义一个新对象并用一个同类型的对象对它进行初始化时,将显式使用复制构造函数。当将该类型的对象传递给函数或函数返回该类型的对象时,将隐式使用复制构造函数

析构函数是构造函数的互补:当对象超出作用域或动态分配的对象被删除时,将自动应用析构函数。析构函数可用于释放对象时构造或在对象的生命期中所获取的资源。不管类是否定义了自己的析构函数,编译器都自动执行类中非 static 数据成员的析构函数

与构造函数一样,赋值操作符可以通过指定不同类型的右操作数而重载。右操作数为类类型的版本比较特殊:如果我们没有编写这种版本,编译器将为我们合成一个。

复制构造函数、赋值操作符和析构函数总称为复制控制。编译器自动实现这些操作,但类也可以定义自己的版本。

通常,编译器合成的复制控制函数是非常精练的——它们只做必需的工作。但对某些类而言,依赖于默认定义会导致灾难。实现复制控制操作最困难的部分,往往在于识别何时需要覆盖默认版本。有一种特别常见的情况需要类定义自己的复制控制成员的:类具有指针成员

  • 复制构造函数

只有单个形参,而且该形参是对本类类型对象的引用(常用 const 修饰),这样的构造函数称为复制构造函数。与默认构造函数一样,复制构造函数可由编译器隐式调用。复制构造函数可用于:

根据另一个同类型的对象显式或隐式初始化一个对象;复制一个对象,将它作为实参传给一个函数;从函数返回时复制一个对象;初始化顺序容器中的元素;根据元素初始化式列表初始化数组元素

  • 对象的定义形式

C++ 支持两种初始化形式:直接初始化和复制初始化。复制初始化使用 = 符号,而直接初始化将初始化式放在圆括号中

当用于类类型对象时,初始化的复制形式和直接形式有所不同:直接初始化直接调用与实参匹配的构造函数,复制初始化总是调用复制构造函数。复制初始化首先使用指定构造函数创建一个临时对象,然后用复制构造函数将那个临时对象复制到正在创建的对象

string null_book = "9-999-99999-9"; // copy-initialization
     string dots(10, .);               // direct-initialization

     string empty_copy = string();       // copy-initialization
     string empty_direct;                // direct-initialization

对于类类型对象,只有指定单个实参或显式创建一个临时对象用于复制时,才使用复制初始化

创建 dots 时,调用参数为一个数量和一个字符的 string 构造函数并直接初始化 dots 的成员。创建 null_book 时,编译器首先调用接受一个 C 风格字符串形参的 string 构造函数,创建一个临时对象,然后,编译器使用 string 复制构造函数将 null_book 初始化为那个临时对象的副本。empty_copyempty_direct 的初始化都调用默认构造函数。对前者初始化时,默认构造函数函数创建一个临时对象,然后复制构造函数用该对象初始化 empty_copy。对后者初始化时,直接运行 empty_direct 的默认构造函数

支持初始化的复制形式主要是为了与 C 的用法兼容。当情况许可时,可以允许编译器跳过复制构造函数直接创建对象,但编译器没有义务这样做

通常直接初始化和复制初始化仅在低级别上存在差异。//何为低级别?然而,对于不支持复制的类型(如下面的ifstream),或者使用非 explicit 构造函数(允许隐式类型转换)的类型,它们有本质区别:

ifstream file1("filename"); // ok: direct initialization//利用了构造函数
     ifstream file2 = "filename"; // error: copy constructor is private//企图利用复制构造函数
     // This initialization is okay only if
     // the Sales_item(const string&) constructor is not explicit
     Sales_item item = string("9-999-99999-9");

file1 的初始化是正确的。ifstream 类定义了一个可用 C 风格字符串调用的构造函数,使用该构造函数初始化 file1。看上去等效的 file2 初始化使用复制初始化,但该定义不正确。由于不能复制 IO 类型的对象,所以不能对那些类型的对象使用复制初始化。item 的初始化是否正确,取决于正在使用哪个版本的 Sales_item 类。某些版本将参数为一个 string 的构造函数定义为 explicit(不允许隐式的类型转换)。如果构造函数是显式的,则初始化失败;如果构造函数不是显式的,则初始化成功。

  • 形参与返回值

正如我们所知,当形参为非引用类型的时候,将复制实参的值。类似地,以非引用类型作返回值时,将返回 return 语句 中的值的副本。

当形参或返回值为类类型时,由复制构造函数进行复制。例如:

// copy constructor used to copy the return value;
     // parameters are references, so they aren‘t copied
     string make_plural(size_t, const string&, const string&);

这个函数隐式使用 string 复制构造函数返回给定单词的复数形式。形参是 const 引用,不能复制。

  • 初始化容器的元素

复制构造函数可用于初始化顺序容器中的元素。例如,可以用表示容量的单个形参来初始化容器。容器的这种构造方式使用默认构造函数和复制构造函数:

// default string constructor and five string copy constructors invoked
     vector<string> svec(5);

编译器首先使用 string 默认构造函数创建一个临时值来初始化 svec,然后使用复制构造函数将临时值复制到 svec 的每个元素。作为一般规则,除非你想使用容器元素的默认初始值,更有效的办法是,分配一个空容器并将已知元素的值加入容器。

 

 

复制控制

原文:http://www.cnblogs.com/predator-wang/p/5210947.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!