Разница между `vector <int>v;` и `vector <int>v = vector <int>();` - PullRequest
0 голосов
/ 01 марта 2019

В чем разница между

std::vector<int> v;

и

std::vector<int> v = std::vector<int>();

Интуитивно я бы никогда не использовал вторую версию, но я не уверен, есть ли какая-либо разница.Мне кажется, что вторая строка - это просто конструктор по умолчанию, строящий временный объект, который затем перемещается оператором присваивания перемещения.

Мне интересно, не является ли вторая строка каким-либо образом эквивалентной

std::vector<int> v = *(new std::vector<int>()); 

, следовательно, сам вектор оказывается в куче (динамически распределяется).Если это так, то первая строка, вероятно, предпочтительнее для большинства случаев.

Чем отличаются эти строки кода?

Ответы [ 3 ]

0 голосов
/ 01 марта 2019

Начиная с C ++ 17, нет никакой разницы.

Есть один нишевый вариант использования, где синтаксис инициализации std::vector = std::vector весьма полезен (хотя и не для построения по умолчанию): когда нужно предоставить "count, value "initializer для std::vector<int> члена класса непосредственно в определении класса:

struct S {
  std::vector<int> v; // Want to supply `(5, 42)` initializer here. How?
};

Инициализаторы в классе поддерживают только синтаксис = или {}, что означает, что мы не можем просто сказать

struct S {
  std::vector<int> v(5, 42); // Error
};

Если мы используем

struct S {
  std::vector<int> v{ 5, 42 }; // or = { 5, 42 }
};

, компилятор будет интерпретировать его как список значений вместо пары «count, value», а это не то, что нам нужно.

Итак, один правильный способ сделать это -

struct S {
  std::vector<int> v = std::vector(5, 42);
};
0 голосов
/ 01 марта 2019

Вы спрашивали:

В чем разница между

std::vector<int> v;

и

std::vector<int> v = std::vector<int>();

?

Как утверждают другие, начиная с C ++ 17, в принципе нет разницыЧто касается предпочтений того, какой из них использовать, я бы предложил следующее:

  • Если вы создаете пустой вектор, который будет заполнен позже, то первая версия является более желательным кандидатом.
  • Если вы создаете вектор со значением по умолчанию в качестве одного из его членов или с указанным числом, то будет использоваться более поздняя версия.
  • Обратите внимание, что следующие два являются разными конструкторами:
    • std::vector<int> v = std::vector<int>();
    • Не тот же конструктор, что и:
    • std::vector<int> v = std::vector<int>( 3, 10 );
    • Версия конструктора 2 и является перегруженным конструктором.
  • В противном случае, если вы строите вектор из набора чисел, чем у вас есть следующиеопции:

Вот список std::vector конструкторов .

0 голосов
/ 01 марта 2019

1-й - инициализация по умолчанию , 2-й - инициализация копирования ;Эффект здесь тот же, то есть инициализировать объект v через конструктор по умолчанию std::vector.

Для std::vector<int> v = std::vector<int>();, в принципе он создаст временный std::vector, а затем использует его для перемещения-конструированияобъект v (обратите внимание, что здесь нет назначения).Согласно copy elision (поскольку C ++ 17 это гарантировано), он просто вызовет конструктор по умолчанию для прямой инициализации v.

При следующих обстоятельствах:компиляторы обязаны опускать конструкции копирования и перемещения объектов класса, даже если конструктор копирования / перемещения и деструктор имеют наблюдаемые побочные эффекты.Объекты создаются непосредственно в хранилище, где они в противном случае были бы скопированы / перемещены.Конструкторы копирования / перемещения не обязательно должны присутствовать или быть доступными, поскольку языковые правила гарантируют, что операция копирования / перемещения не выполняется, даже концептуально:

  • При инициализации переменной, когдаВыражение инициализатора - это значение того же типа класса (игнорируя квалификацию cv), что и тип переменной:

    T x = T(T(f())); // only one call to default constructor of T, to initialize x
    

(до C ++ 17 разрешение на копированиеоптимизация.)

это оптимизация: даже если это происходит и конструктор копирования / перемещения (начиная с C ++ 11) не вызывается, он все равно должен присутствовать и быть доступным (как если быоптимизация вообще не проводилась),

Кстати: в обоих случаях никакие объекты std::vector (включая потенциальные временные) не будут построены с динамической продолжительностью хранения с помощью выражения new.

...