2011-08-13 22 views
9

Tôi tự hỏi nếu tôi hiểu đúng emplace_backC++ 0x emplace_back với mục phi copyable

#include <vector> 
using namespace std; 

struct Hero { 
    Hero(const string&) {} 
    Hero(const char*) {} 
    Hero(int) {} 
    // forbid a clone: 
    Hero(const Hero&) = delete; 
    Hero& operator=(const Hero&) = delete; 
}; 

int main() { 
    vector<Hero> heros1 = { "Bond", "Hulk", "Tarzan" }; // ERR: copies? 

    vector<Hero> heros; 
    heros.emplace_back(5);    // ERR: copies 
    heros.emplace_back(string("Bond")); // ERR: copies 
    heros.emplace_back("Hulk");   // ERR: copies 
} 

Vì vậy, tôi thực sự tự hỏi Nếu tôi hiểu sai emplace_back: Tôi mặc dù nó sẽ ngăn chặn để tạo một bản sao của Hero, bởi vì nó tạo mục tại chỗ.

Hoặc là lỗi triển khai trong g ++ - 4.7.0 của tôi?

+2

Không còn C++ 0x nữa. Nó chỉ là C + + ngay bây giờ! ':)' –

Trả lời

6

Bạn cần phải xác định một constructor di chuyển và di chuyển-nhượng nhà điều hành, như thế này:

struct Hero { 
    Hero(const string&) {} 
    Hero(const char*) {} 
    Hero(int) {} 

    Hero(Hero&&) {} 
    Hero& operator=(Hero&&) { return *this; } 

    // forbid a clone: 
    Hero(const Hero&) = delete; 
    Hero& operator=(const Hero&) = delete; 
}; 

này cho phép giá trị của loại anh hùng sẽ được chuyển vào hàm. Di chuyển thường nhanh hơn bản sao. Nếu loại không thể sao chép hoặc không thể di chuyển được thì bạn không thể sử dụng loại này trong một số std::vector.

+1

Cũng cần lưu ý rằng chúng sẽ được tạo cho bạn nếu chúng bị thiếu, đó là lý do mã được biên dịch và chạy –

+0

điều này là phi lý. Nếu bạn cần một hàm tạo di chuyển thì vị trí không thực sự chuyển tiếp hàm tạo ** inplace ** vào bất kỳ đối số variadic nào, bạn vẫn đang tạo một bản sao được di chuyển. Điều đó sẽ làm cho emplace_back hoàn toàn vô dụng – lurscher

+2

@lurscher Để được sử dụng trong một 'std :: vector', tất cả các đối tượng phải có thể sao chép hoặc di chuyển được. –

3

Uh ... Tôi hiểu rồi.

Nếu tôi forbit để bản sao các Hero s, tôi phải cho phép họ di chuyển , nếu tôi muốn đặt chúng trong các thùng chứa. Tôi thật ngốc nghếch.

struct Hero { 
    Hero(const string&) {} 
    Hero(const char*) {} 
    Hero(int) {} 
    // no clone: 
    Hero(const Hero&) = delete; 
    Hero& operator=(const Hero&) = delete; 
    // move only: 
    Hero(Hero&&) {} 
    Hero& operator=(Hero&&) {} 
}; 

Và tất cả các ví dụ ngoại trừ danh sách initializer hoạt động.

+7

Lưu ý rằng chính 'emplace_back' không * không * yêu cầu loại có thể di chuyển được - nó xây dựng mục tại chỗ như bạn nghĩ. Tuy nhiên, 'std :: vector' * nói chung * yêu cầu loại phần tử của nó phải di chuyển hoặc có thể sao chép được, nếu không thì nó không thể phát triển khi cần. – JohannesD

4

Không có lỗi triển khai nào - bạn không cung cấp hàm tạo di chuyển.

+0

Bạn đã nhanh chóng! Tôi cũng chỉ cần gõ câu trả lời của riêng mình ;-) – towi