C ++: copy containers efficiently

How to copy STL containers?

// big containers of POD
container_type<pod_type> source;
container_type<pod_type> destination

// case 1
destination = source;

// case 2
destination.assign(source.begin(), source.end());

// case 3 assumes that destination.size() >= source.size()
copy(source.begin(), source.end(), destination.size());

I use case 1 when possible. Case 2 is intended for containers of different types. Case 3 is necessary when the destination is larger than the source and you want to save the rest of the elements.

But what about non-POD elements with non-zero construction / demolition costs? Could case 3 be better than case 2? If the destination is larger than the source, the implementation can do quite unexpected things. This is what Visual Studio 2008 does in case 2.

  • All recipient items are destroyed.
  • Then, the copy constructor is called as many times as the size of the destination. Why?
  • All source elements are assigned to the corresponding destination elements.
  • Additional recipient elements are destroyed.

GCC 4.5 . , . case 3 ( , ). , , .

#include <iostream>
#include <vector>
#include <list>
#include <algorithm>
using namespace std;

struct A {
    A() { cout << "A()\n"; }
    A(const A&) { cout << "A(const A&)\n"; }
    A& operator=(const A&) {
        cout << "operator=\n";
        return *this;
    }
    ~A() { cout << "~A()\n"; }
};

int main() {
    list<A> source(2);
    vector<A> desrination1(3);
    vector<A> desrination2(3);

    cout << "Use assign method\n";
    desrination1.assign(source.begin(), source.end());

    cout << "Use copy algorithm\n";
    copy(source.begin(), source.end(), desrination2.begin());
    desrination2.resize(2);

    cout << "The End" << endl;
    return 0;
}
+3
2

. , . ?

, . :

 template<class Iterator>
 void assign(Iterator first, Iterator last)
 {
      erase(begin(), end()); // Calls the destructor for each item
      insert(begin(), first, last); // Will not call destructor since it should use placemenet new
 }

- :

assert(source.size() <= destination.size());
destination.erase(copy(source.begin(), source.end(), destination.begin()), destination.end());

. , , ( , / ), , . , , resize() , resize() , .

GCC 4.5 . , . 3, , ( , ). , .

. .

class A
{
     A& operator=(A other)
     {
         std::swap(*this, other);
         return *this;
     }

     // Same thing but a bit more clear
     A& operator=(const A& other)
     {
         A temp(other); // copy assignment
         std::swap(*this, temp);
         return *this;
     }
}
+4

, . , std::copy. , POD.

/ , .

0

Source: https://habr.com/ru/post/1757448/


All Articles