Разница между auto и decltype в С++ 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])' для выделения памяти для типа [0] * b [0]? И я не могу отличить разницу между decltype и auto в этом случае.

Ответы

Ответ 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);, не создавать новые и не использовать устаревшие).