Яка різниця між старшим aloctaor :: конструктом та новим та явним конструктором?


15

Як я знаю, std::allocator<T>::constructу старій версії C ++ приймаються лише два параметри; перший - вказівник на сиру, небудовану пам'ять, в якій ми хочемо побудувати об'єкт типу, Tа другий - значення типу елемента для ініціалізації цього об’єкта. Отже, викликається конструктор копій:

struct Foo {
    Foo(int, int) { cout << "Foo(int, int)" << endl; }
    /*explicit*/ Foo(int) { cout << "Foo(int)" << endl; }
    Foo(const Foo&) { cout << "Foo(const Foo&)" << endl; }
};

int main(int argc, char* argv[]) {


    allocator<Foo> a;
    Foo* const p = a.allocate(200, NULL); // second parameter is required on C++98 but on C++11 it is optional
//  Foo* const p = a.allocate(200); // works fine on C++11 but not on C++98

    a.construct(p, 5, 7); // works on C++ 11 and up but not C++98
    a.construct(p, 10);// works on both
    a.destroy(p);
    a.destroy(p + 1);
    a.deallocate(p, 200);



    std::cout << std::endl;
}
  • Чому на C ++ 98 a.construct(p, 10)виклик конструктора копіювання, а на C ++ 11 і вище викликає лише конструктор, який приймає ціле число?

  • Чи означають це на C ++ 11 з - за деяку оптимізацію копіювання Elision навіть якщо конструктор Foo(int)є explicitроботою за таким викликом: a.construct(p, 5)працює на C ++ 11 навіть конструктор , explicitщо я впевнений , це не працює на C ++ 98 , якщо Foo(int)є explicit.

  • Якщо так, якщо я компілюю цей оператор з якоюсь відключенням copy-elisionоптимізації, це призведе до відмови компілятора? Дякую.


3
Коротка відповідь: до C ++ 11 не було ідеального перебігу . Деталі, надані нижче від @flyx. Зауважте, що жодна копія елісії не задіяна (немає прохідних значень або повернення за значенням).
Даніель Лангр

Відповіді:


13

Це тому, що декларація про construct зміну в C ++ 11 :

void construct( pointer p, const_reference val );  (1)  (until C++11)
template< class U, class... Args >
void construct( U* p, Args&&... args );            (2)  (since C++11)

Перша декларація викликає конструктор копії, тоді як друга декларація викликає конструктор, який відповідає заданому списку аргументів. Це може бути конструктор копій, але й інший конструктор, як ви бачили у своєму коді.

a.construct(p, 10)викликає конструктор копіювання в C ++ 98, тому що 10імпліцитно перетворюється Fooв Foo(int)конструктор. Ця конверсія не потрібна в C ++ 11, оскільки існує відповідний конструктор, який приймає int(саме той конструктор, який використовувався для перетворення в C ++ 98). Це також причина , чому код не працює в C ++ 98 при додаванні explicit- він не може перетворити 10до Fooтоді.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.