Какой конструктор вызывается здесь? - PullRequest
7 голосов
/ 31 марта 2012

В этом фрагменте кода какой конструктор на самом деле называется?

Vector v = getVector(); 

Вектор имеет конструктор копирования, конструктор по умолчанию и оператор присваивания:

class Vector {
public:
    ...
    Vector();
    Vector(const Vector& other);
    Vector& operator=(const Vector& other);
};

getVector возвращает значение.

Vector getVector();

Код использует стандарт C ++ 03.

Фрагмент кода выглядит так, как будто он должен вызывать конструктор по умолчанию, а затем оператор присваивания, но я подозреваю, что это объявление является еще одной формой использования конструктора копирования,Что правильно?

Ответы [ 4 ]

8 голосов
/ 31 марта 2012

Когда в инициализации появляется =, он вызывает конструктор копирования. Общая форма не совсем такая же, как прямой вызов конструктора копирования. В операторе T a = expr; происходит следующее: если expr имеет тип T, вызывается конструктор копирования. Если expr не относится к типу T, то сначала выполняется неявное преобразование, если возможно, затем вызывается конструктор копирования с этим аргументом. Если неявное преобразование невозможно, то этот код некорректен.

В зависимости от того, как структурирована getVector(), копия может быть оптимизирована, а созданный внутри функции объект - это тот же физический объект, который сохраняется в v.

2 голосов
/ 31 марта 2012

Предполагая, что вы не сделали что-то патологическое вне кода, который вы показываете, ваша декларация является инициализацией копирования, и применяется вторая часть этого правила:

13.3.1.3 Initialization by constructor [over.match.ctor]

1 When objects of class type are direct-initialized (8.5), or copy-initialized from an 
  expression of the same or a derived class type (8.5), overload resolution selects the
  constructor. For direct-initialization, the candidate functions are all the constructors
  of the class of the object being initialized. For copy-initialization, the candidate 
  functions are all the converting constructors (12.3.1) of that class. The argument 
  list is the expression-list within the parentheses of the initializer.

Для простого тестаслучай, см. сообщение Эли Бендерского, здесь: http://eli.thegreenplace.net/2003/07/23/variable-initialization-in-c/

1 голос
/ 31 марта 2012

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

Чтобы добавить Далее,

Дело 1:

Vector v1;
Vector v(v1);

Дело 2:

   Vector v = getVector(); 

В двух вышеуказанных форматах Случай 1 равен Прямая инициализация , а Случай 2 известен как Копировать инициализацию .

Как работает копирование инициализации?
Копирование инициализации создает неявную последовательность преобразования: она пытается преобразовать возвращаемое значение getVector() в объект типа Vector.Затем он может скопировать созданный объект в инициализируемый объект, поэтому ему нужен доступный конструктор копирования.

0 голосов
/ 31 марта 2012

В этом случае конструктор копирования фактически исключается (отметьте this ), и только конструктор по умолчанию в итоге получает вызов

EDIT:

Конструктор исключается лишь иногда, согласно ответу Бенджамина. По какой-то причине я прочитал это, когда вы вызываете конструктор напрямую.

...