14

Это просто предпочтение или существуют конкретные случаи, когда один необходим другому? Я ссылаюсь на следующие варианты инициализацииКогда вы должны использовать прямую инициализацию и при инициализации копии?

T t(e); // direct initialization 
T t = e; // copy initialization 
+1

Что такое неявное присваивание? Вы имеете в виду оператор присваивания по умолчанию? – ybungalobill 2010-11-27 20:02:47

+1

Что вы подразумеваете под «неявным назначением». – 2010-11-27 20:03:08

+0

bool bValue1 = true; // Явное назначение bool bValue2 (false); // неявное назначение Это имеет значение? – Mike 2010-11-27 20:11:12

ответ

19

Фактические названия вещей, которые вы описываете, не неявное и явное назначение, но:

  • Прописи инициализации: T x = a;
  • Прямая инициализация : T x(a);

Они не эквивалент, в первую очередь в контексте, где требуется преобразование, например, когда T имеет тип класса, а a имеет другой тип (см. комментарий Alf для примеров контекстов, которые даже не включают преобразование). Рассмотрим следующий код:

class Test 
{ 
public: 
    explicit Test(int i) { /* ... */ } 
}; 

int main() 
{ 
    Test t(0); // OK : calls Test::Test(int) 
    Test u = 0; // KO : constructor is marked explicit 
} 

перефразировать стандарта (8,5/14):

  • Для прямого инициализации и копирования-инициализации, где тип источника является такой же, как или производный класс , класс назначения, конструкторов считаются
  • Для других случаев копирования инициализации, как во второй строке main в моем примере, определенного пользователь последовательности преобразования считается. Поскольку использование конструктора Test для неявного преобразования было запрещено с помощью ключевого слова explicit, вторая строка не скомпилируется.
10

Прямая инициализация как

std::istringstream stream("blah blah"); 

необходимо, когда тип в вопросе, здесь std::istringstream из стандартной библиотеки С ++, не доступный конструктор копирования.

инициализация копии, как

std::istringstream stream = "blah blah"; //! NOT VALID 

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

В другом направлении на C++ 98 необходим синтаксис инициализации копии, чтобы использовать инициализаторы фигурных скобок . Например, прямая инициализация не может использоваться для инициализации агрегата. Но вы можете использовать инициализацию копирования с инициализатором фигурных скобок:

#include <string> 
using namespace std; 

struct Answer 
{ 
    int  nVotes; 
    string description; 
};  

int main() 
{ 
    Answer const incorrect = { 26, "they're the same!" }; 
    Answer const correct  = { -1, "nah, they're different, actually" }; 
} 

Таким образом, существуют существенные различия.

Я обычно предпочитаю синтаксис инициализации копирования из-за ясности. Но иногда, как показано выше, прямая инициализация, к сожалению, необходима. Некоторые люди, например.Автор текста в стиле C++ Фрэнсис Стеклобор, вместо этого приземлился на прямую инициализацию в качестве своего предпочтительного синтаксиса инициализации (я не уверен, почему это менее ясно для моих глаз и представляет проблему «самого неприятного разбора»), и для них это необходимость копирование в некоторых случаях, что является неудачным.

Приветствия & НТН.,