Значение-инициализация автоматического объекта? - PullRequest
30 голосов
/ 09 июня 2011

Я пишу шаблонный класс, и в какой-то момент мой код хотел бы иметь возможность инициализировать значение объекта параметризованного типа в стеке. Прямо сейчас я выполняю это, написав что-то на этот счет:

template <typename T> void MyClass<T>::doSomething() {
    T valueInitialized = T();
    /* ... */
}

Этот код работает, но (если компилятор не умен), он требует ненужного создания и уничтожения временного объекта T. Я хотел бы написать следующее: я знаю, что это неправильно:

template <typename T> void MyClass<T>::doSomething() {
    T valueInitialized(); // WRONG: This is a prototype!
    /* ... */
}

Мой вопрос заключается в том, существует ли хороший способ инициализации значения автоматического объекта без необходимости явно создавать временный объект и присваивать его автоматическому объекту. Можно ли это сделать? Или T var = T(); так хорошо, как это получается?

Ответы [ 3 ]

23 голосов
/ 09 июня 2011

В следующем примере используется copy-initialization , что, вероятно, нормально в 95% случаев в C ++ 03:

T var = T();

Но для generic C ++ 03 код, вы всегда должны предпочитать прямую инициализацию для учета этих других 5%:

T var((T())); // extra parentheses avoid the most vexing parse – the extra parentheses
              // force the contents to be evaluated as an expression, thus implicitly
              // *not* as a declaration.

Или еще лучше, используйте Boost . Utility.ValueInit библиотека, которая упаковывает идеальное поведение для вас вместе с обходными путями для различных недостатков компилятора (к сожалению, больше, чем можно подумать):

boost::value_initialized<T> var;

ДляC ++ 11, можно использовать синтаксис инициализации списка для достижения прямой инициализации значения значительно менее шумно / безобразно:

T var{}; // unambiguously value-initialization*

(* Nb это только инициализация значения для типов, которые неиметь унарный конструктор, принимающий std::initializer_list<>; для типов, которые его делают, этот конструктор будет вызываться вместо этого - действительно, "равномерная инициализация" ... Конечно, чистый результат должен быть одинаковым для вменяемых типов.)

16 голосов
/ 09 июня 2011

Вы можете использовать фигурные скобки в C ++ 0x:

T valueInitialized{};
5 голосов
/ 09 июня 2011

Нет, в C ++ 03 нет другого способа надежно инициализировать значение типа шаблона.

Если вы можете рассчитывать на T только как на типы классов с конструкторами по умолчанию, вы можете просто написать

T valueInitialized;

, но если T также может быть встроенным типом,

T valueInitialized = T();

- это путь.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...