Конструктор копирования против оператора присваивания с вектором STL - PullRequest
2 голосов
/ 15 апреля 2020

Имея этот класс:

class A
{
    int number;
    int number2;
public:
    A(int _number):number(_number),number2(0)
    {
        cout<<"Normal constructor\n";
    }
    A()
    {
        cout<<"Default constructor\n";
    }

    A(const A& source)
    {
        number = source.number;
        number2 = source.number2;
        cout<<"Copy constructor\n";
    }

    A & operator=(const A& source)
    {
        number = source.number;
        number2 = source.number2;
        cout<<"Assignment operator\n";
        return *this;
    }
};

Если создается vector<A> obj {1,2,3}, normal constructor вызывается три раза, потому что он не объявлен как explicit и, следовательно, используется как converting constructor. Затем copy constructor вызывается три раза.

  • Есть ли способ объявить и создать экземпляр vector при пропуске операции копирования?

Если vector<A> obj_1; выполняется, создается пустой вектор, который может содержать объекты типа A - нет конструкторов с именем , , но объект существует .

  • Почему нет конструктора с именем?
  • Я объявил объект таким, что он полностью работоспособен?

От по этой ссылке :

  1. Конструктор копирования используется для инициализации ранее неинициализированного объекта из данных некоторых других объектов.

  2. Оператор присваивания используется для замены данных ранее инициализированного объект с данными другого объекта.


Выполнение obj_1 = obj, если мой obj_1 был предварительно инициализирован, приводит к вызову функции copy constructor вместо operator= внутри моего класса A как я ожидал?

Также внутри vector уже есть функция operator=. Как я могу узнать, когда будет звонить каждый?

vector<A> obj {1,2,3};
vector<A> obj_1;
obj_1 = obj;  // Why copy constructor called instead of function operator= inside my class

1 Ответ

3 голосов
/ 15 апреля 2020

Есть ли способ объявить и создать экземпляр vector при пропуске операции копирования?

Нет. Когда вы делаете vector<A> obj {1,2,3}, компилятор создает std::initializer_list<A> из предоставленных значений. Это std::initializer_list создание - причина, по которой вы видите три обычных вызова конструктора. Затем вектор должен скопировать эти элементы, поскольку базовое хранилище для этих элементов - const. Там не было обойти это с помощью инициализации списка. Даже vector<A> obj {A(1),A(2),A(3)} все равно приведет к копированию.

Если вы не хотите этого, то вы можете создать хранилище для элементов, используя reserve, а затем использовать emplace_back для непосредственного конструирования объектов. в векторе, таком как

vector<A> obj;
obj.reserve(3);
for (int i = 1; i < 4, ++i)
    obj.emplace_back(i);

Выполнение obj_1 = obj, если мой obj_1 был предварительно инициализирован, приводит к вызову конструктора копирования вместо функции operator= внутри моего класса A, как я ожидал?

Это потому, что obj_1 пусто. Поскольку он пуст, отсутствует элемент для вызова оператора присваивания. Вместо этого он создает элементы в obj_1, которые являются копиями obj, и наиболее эффективный способ сделать это - просто вызвать конструктор копирования вместо создания объектов по умолчанию и затем присвоить им.

Если бы у вас было

vector<A> obj {1,2,3};
vector<A> obj_1 {3, 4, 5};
obj_1 = obj; 

Вместо этого вы бы увидели, что вместо этого будет использоваться оператор присваивания, поскольку есть объекты, которые фактически должны быть назначены.

...