В чем разница между старым alloctaor :: construct и новым и явным конструктором? - PullRequest
11 голосов
/ 07 ноября 2019

Как я знаю * 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 из-за некоторой оптимизации с копированием, даже если конструктор Foo(int) равен explicit работает с таким вызовом: a.construct(p, 5) работает сC ++ 11, даже конструктор explicit, в чем я уверен, он не работает на C ++ 98, если Foo(int) равен explicit.

  • Если тактогда, если я скомпилирую этот оператор с некоторым отключением оптимизации copy-elision, произойдет сбой компилятора? Спасибо.

1 Ответ

12 голосов
/ 07 ноября 2019

Это потому, что объявление 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 тогда.

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