Является ли std:: векторное копирование объектов с помощью push back?
после многих исследований с valgrind, я сделал вывод, что std::vector делает копию объекта, который вы хотите push_back.
Это правда ? Вектор не может хранить ссылку или указатель объекта без копии ?!
спасибо
8 ответов:
Да
std::vector<T>::push_back()
создает копию аргумента и сохраняет его в векторе. Если вы хотите сохранить указатели на объекты в вашем векторе, создайтеstd::vector<whatever*>
вместоstd::vector<whatever>
.однако вам нужно убедиться, что объекты, на которые ссылаются указатели, остаются действительными, пока вектор содержит ссылку на них (интеллектуальные указатели, использующие идиому RAII, решают проблему).
Да
std::vector
хранит копии. Как должноvector
знаете, что ожидаемое время жизни ваших объектов?Если вы хотите передать или разделить право собственности на объекты, используйте указатели, возможно, умные указатели, такие как
shared_ptr
(находится в Boost или TR1) для облегчения управления ресурсами.
начиная с C++11, все стандартные контейнеры (
std::vector
,std::map
и т. д.) поддержка семантики перемещения, что означает, что теперь вы можете передавать значения rvalues в стандартные контейнеры и избегать копирования:// Example object class. class object { private: int m_val1; std::string m_val2; public: // Constructor for object class. object(int val1, std::string &&val2) : m_val1(val1), m_val2(std::move(val2)) { } }; std::vector<object> myList; // #1 Copy into the vector. object foo1(1, "foo"); myList.push_back(foo1); // #2 Move into the vector (no copy). object foo2(1024, "bar"); myList.push_back(std::move(foo2)); // #3 Move temporary into vector (no copy). myList.push_back(object(453, "baz")); // #4 Create instance of object directly inside the vector (no copy, no move). myList.emplace_back(453, "qux");
в качестве альтернативы вы можете использовать различные смарт-указатели, чтобы получить в основном тот же эффект:
std::unique_ptr
примерstd::vector<std::unique_ptr<object>> myPtrList; // #5a unique_ptr can only ever be moved. auto pFoo = std::make_unique<object>(1, "foo"); myPtrList.push_back(std::move(pFoo)); // #5b unique_ptr can only ever be moved. myPtrList.push_back(std::make_unique<object>(1, "foo"));
std::shared_ptr
примерstd::vector<std::shared_ptr<object>> objectPtrList2; // #6 shared_ptr can be used to retain a copy of the pointer and update both the vector // value and the local copy simultaneously. auto pFooShared = std::make_shared<object>(1, "foo"); objectPtrList2.push_back(pFooShared); // Pointer to object stored in the vector, but pFooShared is still valid.
std:: vector всегда делает копию того, что хранится в векторе.
Если вы сохраняете вектор указателей, то он будет делать копию указателя, но не экземпляр, на который указывает указатель. Если вы имеете дело с крупными объектами, вы можете (и вероятно должны) всегда использовать вектор указателей. Часто использование вектора интеллектуальных указателей соответствующего типа хорошо для целей безопасности, так как обработка времени жизни объекта и управление памятью могут будь хитрым в противном случае.
не только std::vector делает копию того, что вы отталкиваете, но определение коллекции утверждает, что это будет сделано, и что вы не можете использовать объекты без правильной семантики копирования в векторе. Так, например, вы не используете auto_ptr в векторе.
релевантным в C++11 является
emplace
семейные функции-члены, которые позволяют передавать права собственности на объекты, перемещая их в контейнеры.идиома использования будет выглядеть как
std::vector<Object> objs; Object l_value_obj { /* initialize */ }; // use object here... objs.emplace_back(std::move(l_value_obj));
перемещение для объекта lvalue важно, так как в противном случае он будет перенаправлен как ссылка или ссылка const, и конструктор перемещения не будет вызван.
Если вы не хотите копии; то лучший способ-использовать вектор указателя(или другую структуру, которая служит для той же цели). если вы хотите копии; используйте непосредственно push_back (). у тебя нет другого выбора.
почему потребовалось много исследований valgrind, чтобы узнать это! Просто докажите это себе с помощью простого кода, например
std::vector<std::string> vec; { std::string obj("hello world"); vec.push_pack(obj); } std::cout << vec[0] << std::endl;
Если печатается "hello world", объект должен быть скопирован