2011-08-13 16 views
9

Zastanawiam się, czy prawidłowo zrozumiałem emplace_backC++ 0x emplace_back z non-copyable Rzeczy

#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 
} 

Tak więc, ja naprawdę zastanawiać, czy mam rozumieć emplace_back niepoprawnie: I choć byłoby zapobiec zrobić kopię z Hero, ponieważ tworzy element w miejscu.

Czy jest to błąd implementacji w moim g ++ - 4.7.0?

+2

To już nie jest C++ 0x. Teraz jest tylko C++! ':)' –

Odpowiedz

6

trzeba określić konstruktora ruch, przesuwanie zadanie operatora, na przykład:

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; 
}; 

Pozwala to wartości typu Hero przeniesione do tej funkcji. Ruch jest zwykle szybszy niż kopiowanie. Jeśli typ nie jest ani kopiowalny, ani ruchomy, nie można go użyć w std::vector.

+1

Należy również zauważyć, że zostaną one wygenerowane dla ciebie, jeśli ich nie ma, dlatego kod skompilowany i uruchomiony –

+0

jest niedorzeczny. Jeśli potrzebujesz konstruktora ruchu, to emplace tak naprawdę nie przesyła ** konstruktora ** inplace ** żadnych argumentów variadic, nadal wykonujesz przeniesioną kopię. To spowodowałoby, że emplace_back byłby całkowicie bezużyteczny. – lurscher

+2

@lurscher Do użycia w 'std :: vector' w ogóle, obiekty muszą być kopiowalne lub ruchome. –

3

Uh ... Rozumiem.

Gdybym forbit do kopii z Hero s, muszę pozwolić im ruchu, jeśli chcę, aby umieścić je w pojemnikach. Ale głuptas ze mnie.

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&&) {} 
}; 

I wszystkie przykłady wyjątkiem listy inicjatora pracy.

+7

Zwróć uwagę, że 'emplace_back' samo * nie * wymaga, aby ten typ był ruchomy - tworzy obiekt na miejscu, tak jak myślałeś. Jednakże, 'std :: vector' * ogólnie * wymaga, aby jego typ elementu był albo ruchomy, albo kopiowalny, inaczej nie mógłby wzrastać w razie potrzeby. – JohannesD

4

Nie jest to błąd implementacji - nie podano konstruktora ruchu.

+0

Byłeś szybki! Właśnie pisałem własną odpowiedź ;-) – towi