2013-06-09 3 views

Odpowiedz

27

Wystarczy zrobić:

#include <iterator> 
#include <algorithm> 

// ... 

void MoveAppend(std::vector<X>& src, std::vector<X>& dst) 
{ 
    if (dst.empty()) 
    { 
     dst = std::move(src); 
    } 
    else 
    { 
     dst.reserve(dst.size() + src.size()); 
     std::move(std::begin(src), std::end(src), std::back_inserter(dst)); 
     src.clear(); 
    } 
} 

Jeśli dst jest pusta, ruch przypisanie z src do dst będzie wykonać zadanie - że będzie tak tanie, jak to może być, po prostu „kradzież” tablicę zamknięty przez src, dzięki czemu dst wskaże go później.

Jeśli dst nie jest pusty, elementy dołączone do dst zostaną skonstruowane z elementów w src. Po wywołaniu std::move(), src nie będzie pusty - będzie zawierał elementy "zombie" przeniesione. Dlatego nadal konieczne jest połączenie z numerem clear().

+1

DST nie jest pusta. –

+0

@ ŁukaszLaw: OK, to zmienia sytuację. Będę edytować –

+0

@ ŁukaszLew: Zmieniłem odpowiedź. Przepraszam za nieporozumienie. –

11

bym nieco wolą to z przyjętą odpowiedzi:

#include <vector> 
#include <iterator> 
#include <utility> 

template <typename T> 
typename std::vector<T>::iterator append(const std::vector<T>& src, std::vector<T>& dest) 
{ 
    typename std::vector<T>::iterator result; 

    if (dest.empty()) { 
     dest = src; 
     result = std::begin(dest); 
    } else { 
     result = dest.insert(std::end(dest), std::cbegin(src), std::cend(src)); 
    } 

    return result; 
} 

template <typename T> 
typename std::vector<T>::iterator append(std::vector<T>&& src, std::vector<T>& dest) 
{ 
    typename std::vector<T>::iterator result; 

    if (dest.empty()) { 
     dest = std::move(src); 
     result = std::begin(dest); 
    } else { 
     result = dest.insert(std::end(dest), 
          std::make_move_iterator(std::begin(src)), 
          std::make_move_iterator(std::end(src))); 
    } 

    src.clear(); 
    src.shrink_to_fit(); 

    return result; 
} 

Przykład:

#include <string> 
#include <algorithm> 
#include <iostream> 

int main() 
{ 
    const std::vector<std::string> v1 {"world", "!"}; 

    std::vector<std::string> v2 {" "}, v3 {"hello"}, v4 {}; 

    append(v1, v2); // copies 
    append(std::move(v2), v3); // moves 
    append(std::move(v3), v4); // moves 

    std::copy(std::cbegin(v4), std::cend(v4), std::ostream_iterator<std::string> {std::cout}); 
    std::cout << std::endl; 
} 
+0

Myślę, że jest to o wiele lepsza odpowiedź, ma przeciążenia dla źródła lwartości i rwartości, i używa std :: vector :: insert(). – dats

+2

Dlaczego "wyczyścisz" źródło rvalue? Myślę, że robi niezapowiedzianą dodatkową pracę. – dats

+0

@dats To interesujący punkt - moim zdaniem to, że dzwoniący oczekuje pojemność źródła rvalue wynosi zero po wywołaniu, co nie byłoby inaczej. – Daniel

Powiązane problemy