First, you must understand that the container holds many objects, but not the original objects you pass to it, but the object copy.
In addition, when you get an object from the container, you don't get the object in the container, but copy the object. Similarly, when you add an object to the container (by using insert or push_back), you add the object to the containerCopy. Copy it in and copy it out. This is the STL method. Therefore, STL requires that the object be copyable. Copying an object to a container is not uncommon. If you insert or delete an element from a vector, string, or deque, the existing element is moved (copied ). If you use any sorting algorithm, the general sorting algorithm requires exchange, and the exchange needs to be copied. There are many such examples.
You may be interested in how all these copies are completed. This is simple. An object is copied by using its copy member function, especially its copy constructor and its copy assignment constructor. This is the legendary big 3. for user-defined classes, such as widgets, these functions are traditionally declared as follows:
class Widget { public: ...
Widget();
Widget (const widget &); // copy the constructor
Widget & operator = (const widget &); // copy the value assignment operator ...};
If you do not declare these functions, your compiler will generate them for you as needed. Copying built-in types (such as int and pointer) is always done by simply copying their binary bit values. (For details about copying constructors and value assignment operators, see any c ++ introductory books. I think you recommend C ++ programming and inside C ++ project model. These two books are very thorough ).
If you fill a container with an expensive copy object, a simple operation-put the object into the container will also prove to be a performance bottleneck. The more things that move in containers, the more memory and CPU clock cycles you will waste on copying. In addition, if you have defined a problematic copy constructor, This will directly affect the container.
Of course, because of inheritance, copying will lead to slicing ). That is to say, if you create a container with a base class object and you try to insert a derived class object, then when the object (through the base class copy constructor) when containers are merged, the derived part of the object is deleted.
Vector <widget> VW; Class specialwidget: // specialwidget derives public widget {...} from the widget above {...}; specialwidget SW; VW. push_back (SW); // SW is written into VW as a base class object, and its subclass is lost when it is copied.
The slicing problem implies that the container that inserts a derived class object into the base class object is almost always wrong. If you want the result object to be a derived class object, for example, calling a virtual function of a derived class, it is always wrong. (For more background information about slicing, see article 22 of Objective C ++ .)
A simple way to make copying more efficient, correct, and avoid splitting problems is to create a pointer container instead of an object container. That is to say, instead of creating a widget container, creating a widget * container. Copying pointers is fast and there is no additional overhead (just copying simple binary values), and there is no slicing Problem When copying pointers. The disadvantage is that the pointer container has another headache. You need to manually delete these pointers. If you do not want to manually delete pointers, smart pointers are a good solution when balancing efficiency, correctness, and slicing.
If all these mechanisms make the STL copy mechanism sound crazy, think about it again. Yes, STL performs a large number of copies. However, during design, it tries its best to avoid unnecessary object copies. In fact, its implementation also tries its best to avoid unnecessary object copies. Compare with C and C ++ built-in container behaviors, the following array:
Widget W [maxnumwidgets]; // create a widgets array with the size of maxnumwidgets. Each element is constructed by default.
Even if we only use some of them or we immediately use the values obtained from a certain place (for example, a file) to overwrite each default constructed value, we also need to construct maxnumwidgets widget objects. Use STL to replace arrays. You can use a vector that can increase as needed:
Vector <widget> VW; // create a vector of 0 widget objects, which can be expanded as needed
We can also create an empty vector that can contain maxnumwidgets widgets, but no widgets are constructed:
Vector <widget> VW;
VW. Reserve (maxnumwidgets );
Compared with arrays, STL containers are more flexible. They only create (by copying) the number of objects you need, and they are only done when you specify. Yes, we need to know that STL containers use copies, but don't forget the fact that they are still an improvement over arrays.