разница между auto и decltype в c++0x
У меня возникли проблемы с auto и decltype.
void f(const vector<int>& a, vector<float>& b)
{
typedef decltype(a[0]*b[0]) Tmp;
for (int i=0; i < b.size(); ++i) {
auto p0 = new auto(a[i]*b[i]);
auto p1 = new decltype(a[i]*b[i]);
*p0=a[i]*b[i];
*p1=a[i]*b[i];
cout<<*p0<<endl;
cout<<*p1<<endl;
delete p0;
delete p1;
}
}
int main()
{
vector<float>vec2;
vec2.push_back(2.0);
vector<int>vec1;
vec1.push_back(5);
return 0;
}
Приведенный выше код хорошо работает в GCC4. 7. Могу ли я использовать "new auto(a[0]*b[0])" для выделения памяти для типа a[0]*b[0]? И я не могу различить разницу между decltype и auto в этом случае.
1 ответ:
Разница в том, что это:
new auto(a[i]*b[i]);
Выделяет объект любого типа
a[i]*b[i]
и инициализирует объект с этим значением. То есть круглые скобки являются инициализатором. В то время как использование decltype:new decltype(a[i]*b[i]);
Выделяет объект того же типа, но нет инициализатора. Объект инициализирован по умолчанию.
В основном
decltype(...)
рассматривается как тип, в то время какauto
определяет тип, который должен быть выведен из интилизатор.
Стиль C++11
Поскольку
new
не следует использовать, кроме как в особых случаях, если по какой-то причине эти семантики необходимы, то они правильно будут написаны примерно так:Кроме того, если человек привыкает использовать универсальную инициализацию C++11 и если он перестает использовать скобки для инициализации, то в конечном итоге скобки, используемые с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])>();
decltype
, перестают выглядеть для программиста как инициализатор.По этой причине и другие, я думаю, что было бы хорошо для "современного" стиля C++11 включить правило, что нужно всегда использовать фигурные скобки и никогда не использовать скобки для инициализации. (И конструкторы, которые не могут быть вызваны иначе как с помощью скобок, например
std::vector<int>(int,int);
, следует избегать; Не создавайте новые и не используйте устаревшие.)