Ответ 1
Разница в том, что это:
new auto(a[i]*b[i]);
выделяет объект любого типа a[i]*b[i]
is и инициализирует объект с этим значением. То есть скобки являются инициализаторами. Принимая во внимание, что с помощью decltype:
new decltype(a[i]*b[i]);
выделяет объект того же типа, но инициализатор отсутствует. Объект инициализируется по умолчанию.
В основном decltype(...)
рассматривается как тип, тогда как auto
указывает тип, который следует выводить из intializer.
Стиль С++ 11
Так как new
не следует использовать, кроме как в особых случаях, если по какой-то причине эти семантики необходимы, они должны быть написаны примерно так:
template<typename T, typename... Args> T make_unique(Args &&...args) {
return std::unique_ptr<T>{std::forward<Args>(args)...};
}
template<typename T> T make_unique_auto(T &&t) {
return std::unique_ptr<T>{std::forward<T>(t)};
}
// new auto(a[i]*b[i])
auto p1 = make_unique_auto(a[i]*b[i]);
// new decltype(a[i]*b[i])
auto p2 = make_unique<decltype(a[i]*b[i])>();
Кроме того, если вы привыкли использовать стандартную инициализацию С++ 11 универсально, и если вы останавливаете использование скобок для инициализации, то в конечном итоге скобки, используемые с decltype
, перестают смотреть на программиста, как инициализатор.
По этой причине и другим, я думаю, было бы хорошо, если бы "современный" стиль С++ 11 включал правило, в котором всегда нужно использовать фигурные скобки и никогда не использовать круглые скобки для инициализации. (И избегать конструкторов, которые нельзя вызывать, кроме как с круглыми скобками, например std::vector<int>(int,int);
, не создавать новые и не использовать устаревшие).