Với struct sau:bản sao khởi vs danh sách khởi tạo trực tiếp tạm
struct ABC
{
ABC(){cout << "ABC" << endl;}
~ABC() noexcept {cout << "~ABC" << endl;}
ABC(ABC const&) {cout << "copy" << endl;}
ABC(ABC&&) noexcept {cout << "move" << endl;}
ABC& operator=(ABC const&){cout << "copy=" << endl;}
ABC& operator=(ABC&&) noexcept {cout << "move=" << endl;}
};
Sản lượng:
std::pair<std::string, ABC> myPair{{}, {}};
là:
ABC
copy
~ABC
~ABC
Trong khi đầu ra của:
std::pair<std::string, ABC> myPair{{}, ABC{}};
là:
ABC
move
~ABC
~ABC
Trong cố gắng để hiểu sự khác biệt giữa hai Tôi nghĩ rằng tôi đã xác định rằng trường hợp đầu tiên được sử dụng bản sao-list-khởi tạo, trong khi một thứ hai sử dụng trực tiếp-list-khởi của một chưa được đặt tên tạm thời (số 7 và 2, tương ứng, tại đây: http://en.cppreference.com/w/cpp/language/list_initialization).
Tìm kiếm các câu hỏi tương tự Tôi đã tìm thấy điều này: Why does the standard differentiate between direct-list-initialization and copy-list-initialization? và điều này: Does copy list initialization invoke copy ctor conceptually?.
Câu trả lời trong những câu hỏi này thảo luận về thực tế là để khởi tạo danh sách sao chép, việc sử dụng một hàm tạo rõ ràng sẽ làm cho mã không đúng định dạng. Trong thực tế, nếu tôi làm cho constructor mặc định của ABC rõ ràng, ví dụ đầu tiên của tôi sẽ không biên dịch nhưng đó là (có lẽ) một vấn đề khác.
Vì vậy, câu hỏi đặt ra là: Tại sao bản sao được sao chép tạm thời trong trường hợp đầu tiên nhưng được di chuyển trong trường hợp thứ hai? Điều gì ngăn cản nó được di chuyển trong trường hợp khởi tạo sao chép danh sách?
Là một lưu ý, các mã sau đây:
std::pair<std::string, ABC> myPair = std::make_pair<string, ABC>({}, {});
Ngoài ra kết quả trong một cuộc gọi đến constructor di chuyển của ABC (và không có cuộc gọi constructor sao chép), nhưng cơ chế khác nhau có thể tham gia.
Bạn có thể thử mã ra (sử dụng gcc-4.9.2 trong chế độ 14 C++) tại địa chỉ: https://ideone.com/Kc8xIn
thế nào có thể hoàn toàn chuyển tiếp constructor được lựa chọn cho 'myPair {{}, ABC {}};' cuộc gọi, nếu nó không thể suy ra 'std :: chuỗi' từ '{}'? –
@MarcAndreson Rất tiếc, tệ của tôi. Tôi đã hiểu sai điều này. Nếu bạn đang sử dụng libstdC++, đây có thể là một phần mở rộng. Hãy để tôi cố gắng tìm nó. – dyp
Lý do cho những quá tải đó chủ yếu là để hỗ trợ các công cụ như 'std :: pair, int *> p (std :: unique_ptr (), 0);'. Xem [PR 40925] (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=40925#c8), –