C++直接初始化,拷贝初始化,调用哪个构造函数?

浪子不回头ぞ 提交于 2020-03-09 09:46:30

很多C++新手不明白直接初始化、拷贝初始化,不清楚初始化过程中使用哪个构造函数。在学习过程中,要有基本概念,并且养成正确的认识也是非常重要的。因此整理了本文。

常见错误认识1:
1.使用()和使用=定义对象没什么区别。(直接初始化、拷贝初始化。)
2.直接初始化使用构造函数。(错,也可能使用拷贝构造函数。)
3.拷贝初始化使用拷贝构造函数。(错,也能使用构造函数。)

直接初始化

如果有一个新对象被定义(即创建了新对象),一定有构造函数被调用。
使用直接初始化时,我们实际上要求编译器使用普通的函数匹配,来提供参数最匹配的构造函数。因此直接初始化可能使用构造函数,也可能使用拷贝构造函数。
简单理解,用()来定义对象的就为直接初始化。

拷贝初始化

按字面意思理解即可,将一个对象给另一个对象初始化。
简单理解,用=定义对象的就为拷贝初始化。

注意:
拷贝赋值运算符也用在=的情况下,但是在对象已经创建并存在的情况下,只是修改对象的值而已。
而用=拷贝初始化是发生在定义一个对象的情况下,即对象此前尚未存在。

类定义如下:

#include <string>
#include <iostream>

class Book
{
public:
    Book() = default;
    Book(std::string s): name(s){std::cout << name << ": 1 para construstor" << std::endl;}
    Book(std::string s, int n): name(s), sum(n){std::cout << name << ": 2 paras construstor" << std::endl;}
    Book(const Book &b): name(b.name), sum(b.sum){std::cout << name << ": copy constructor" << std::endl;}
    Book & operator = (const Book &b) {
        name = b.name;
        sum = b.sum;
        std::cout << name << ": copy-assignment operator" << std::endl;
        return *this;
    }

private:
    std::string name;
    int sum;
};

如果有以下代码,判断,b1~b5初始化时分别使用哪个函数?

    Book b1;
    Book b2("b2");
    Book b3 = string ("b3");
    cout << endl;

    Book b4(b3);
    Book b5 = b3;
    cout << endl;
    
    b1 = string("b1");

1、b1:直接初始化。由于未能提供初始值,使用默认的构造函数。(想定义使用默认构造函数的对象,对象名之后不能有括号,即不能写Book b1()。这种写法意思是定义了一个叫b1的函数,返回值为Book对象。)

2、b2:直接初始化。使用了具有一个string参数的构造参数。

3、b3:拷贝初始化。使用了具有一个string参数的构造函数。

在b3初始化时,分为如下两步:
第一步:使用一个具有string参数的构造函数将string构造为临时Book类对象。
第二部:使用拷贝构造函数将上一步中的Book对象拷贝给b3。
但是实际上,编译器会进行优化,可以跳过拷贝、移动构造函数,直接使用构造函数来构造对象,即优化掉了第一步。

4、b4:直接初始化。使用了拷贝构造函数。因为括号中为Book类对象,最匹配的是拷贝构造函数。

5、b5:拷贝初始化。使用拷贝构造函数。

6、b1: 先使用构造函数将string转为Book类对象,然后将该对象通过赋值运算符来赋值给b1。

测试结果如下:
在这里插入图片描述
参考《C++ primer》13.1.1 P441~P442。

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!