是否为数组/向量插入调用了赋值运算符或复制构造函数?

时间:2018-10-24 19:04:53

标签: c++

语言:C ++

我的问题是在以下情况下是否调用复制构造函数或赋值运算符。在此之前,我了解以下内容:

MyClass a(3);      // single param constructor
MyClass b(a);      // copy constructor invoked
MyClass c = b;     // copy constructor invoked
MyClass d;         // default constructor
d = c;             // assignment operator invoked

但是,我希望有人能对此提供类似的细分:

1)对于第2-3行,是调用赋值运算符还是复制构造函数?

MyClass arr[10];
arr[2] = a;
arr[5] = MyClass(1);

2)构造函数,然后复制构造函数?还是构造函数,然后是赋值运算符?

MyClass arr2[] = {MyClass(), MyClass(9)};

3)假设向量v的内部表示空间还有一个对象,是使用赋值运算符还是复制构造函数复制新元素?

std::vector<MyClass> v;
v.push_back(MyClass(2));
...
...

4)假设向量v的内部表示空间不足并且必须重新分配,是使用赋值运算符复制旧元素还是复制构造函数?

v.push_back(MyClass(2)); // Assuming vector is out of space; must realloc

2 个答案:

答案 0 :(得分:1)

有空

type variable_name = some_value

然后,您将声明一个变量,并且将始终调用其构造函数(如果有)。这称为复制初始化,并且永远不会赋值

所以,在

MyClass arr[10];      // 1
arr[2] = a;           // 2
arr[5] = MyClass(1);  // 3

第1行创建一个包含10个MyClass的数组,并默认构造每个数组。第2行和第3行是分配。

MyClass arr2[] = {MyClass(), MyClass(9)};

您可以使用* braced-init-list`中的值作为数组成员的初始化程序来初始化2个对象的数组。控制list initialization的规则很多,但它们的共同点是不会发生分配,只会进行构造函数调用。

使用

std::vector<MyClass> v;
v.push_back(MyClass(2));

假设向量没有重新分配,您有一个MyClass(2)的构造函数调用,然后向量中的元素是从该临时对象复制构造的。如果必须增加向量,则将所有当前元素复制/移动到新缓冲区中,然后在最后复制临时元素。

答案 1 :(得分:1)

MyClass arr[10];

MyClass的构造函数被调用10次,因为创建了10个arr对象。

arr[2] = a;

调用赋值运算符,将arr[2]分配给a

arr[5] = MyClass(1);

第一个带有参数1的单个param构造函数被调用并创建MyClass对象。然后调用赋值运算符。

MyClass arr2[] = {MyClass(), MyClass(9)};

这里仅调用了两个构造函数。首先是Myclass(),然后是“单个参数构造函数” MyClass(9)。具有初始化的数组声明不是分配,因为不存在要分配给它的现有数组成员。

std::vector<MyClass> v;

std::vector<MyClass>的构造函数被调用。

v.push_back(MyClass(2));

std::vector::push_back创建该类的副本并将其存储。因此,首先调用MyClass(2)构造函数,然后调用复制构造函数MyClass(const MyClass &)复制值。然后将复制的对象存储起来。

  

假设向量v的内部表示空间不足并且必须重新分配,是使用赋值运算符复制旧元素还是复制构造函数?

为每个成员调用复制运算符。所以:

std::vector<MyClass> a;

调用std::vector<MyClass>的构造函数

a.push_back(MyClass(1));

调用MyClass(1)的构造函数,并使用复制余量MyClass(MyClass&)复制它。
之后,如果我们向数组添加另一个元素:

a.push_back(MyClass(2));

然后调用MyClass(2)构造函数,然后为刚刚构造的MyClass(MyClass&)对象的MyClass(2)调用复制构造函数。然后,向量会复制ned的所有现有成员,因此对于向量MyClass(1)中预先存在的对象,将调用已升级的复制构造函数。

真的,玩一点吧。并在所有位置插入cout以查看它:

struct MyClass {
    MyClass(int a = 0) : _a(a) {
        _count = count++;
        std::cout << __func__ << " " 
            << _count << " "
            << this << " "
            << this->_a << "\n";
    }
    MyClass(const MyClass &old_obj) {
        this->_a = old_obj._a;
        std::cout << __func__ << "Copy " 
            << _count << " "
            << this << " "
            << this->_a << " "
            << &old_obj << " "
            << old_obj._a << "\n";
    }
    void operator=(const MyClass &old_obj) {
        this->_a = old_obj._a;
        std::cout << "MyClass" << __func__ << " " 
            << _count << " "
            << this << " "
            << this->_a << " "
            << &old_obj << " "
            << old_obj._a << "\n";
    }
    static int count;
    int _count;
    int _a;
};

int MyClass::count = 0;