Sự khác biệt betwwen của alloctaor :: xây dựng mới và cái mới và hàm tạo rõ ràng là gì?


15

Như tôi biết std::allocator<T>::constructchỉ mất hai tham số trên phiên bản cũ hơn của C ++; đầu tiên là một con trỏ tới bộ nhớ thô, không được xây dựng trong đó chúng ta muốn xây dựng một đối tượng có kiểu Tvà thứ hai là một giá trị của kiểu phần tử để khởi tạo đối tượng đó. Vì vậy, trình xây dựng sao chép được gọi:

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;
}
  • Tại sao trên C ++ 98 a.construct(p, 10)gọi hàm tạo sao chép nhưng trên C ++ 11 trở lên chỉ gọi hàm tạo có số nguyên?

  • Điều này nghĩa là trên C ++ 11 vì một số tối ưu hóa Copy-sự bỏ bớt ngay cả khi các nhà xây dựng Foo(int)explicitcông trình theo yêu cầu như: a.construct(p, 5)công trình trên C ++ 11 thậm chí các nhà xây dựng là explicitnhững gì tôi chắc chắn là nó không hoạt động trên C ++ 98 nếu Foo(int)explicit.

  • Nếu vậy thì nếu tôi biên dịch câu lệnh đó với một số loại copy-elisiontối ưu hóa vô hiệu hóa sẽ khiến trình biên dịch bị lỗi? Cảm ơn bạn.


3
Câu trả lời ngắn: cho đến C ++ 11, không có fowending hoàn hảo . Chi tiết được cung cấp dưới đây bởi @flyx. Lưu ý rằng không có cuộc bầu chọn sao chép liên quan (không có giá trị chuyển tiếp hoặc trả về theo giá trị).
Daniel Langr

Câu trả lời:


13

Điều này là do khai báo construct đã thay đổi trong 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)

Khai báo đầu tiên gọi hàm tạo sao chép, trong khi khai báo thứ hai gọi hàm tạo khớp với danh sách các đối số đã cho. Đây có thể là hàm tạo sao chép, nhưng cũng là hàm tạo khác như bạn đã thấy trong mã của mình.

a.construct(p, 10)gọi hàm tạo sao chép trong C ++ 98 vì 10nó được chuyển đổi hoàn toàn Fooqua hàm Foo(int)tạo. Chuyển đổi này là không cần thiết trong C ++ 11 vì có một hàm tạo phù hợp lấy một int(chính xác là hàm tạo được sử dụng để chuyển đổi trong C ++ 98). Đây cũng là lý do tại sao mã không làm việc trong C ++ 98 khi bạn thêm explicit- nó không thể chuyển đổi 10đến một Foosau đó.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.