태그 보관물: stl

stl

std :: vector가 push_back으로 객체를 복사합니까? 한 후에

valgrind로 많은 조사를 한 후에 std :: vector가 push_back하려는 객체의 사본을 만든다는 결론을 내 렸습니다.

정말 맞습니까? 벡터는 복사본없이 객체의 참조 나 포인터를 유지할 수 없습니다!

감사



답변

예, std::vector<T>::push_back()인수의 복사본을 만들어 벡터에 저장합니다. 벡터의 객체에 대한 포인터를 저장하려면 std::vector<whatever*>대신을 만드십시오 std::vector<whatever>.

그러나 벡터가 참조를 보유하고있는 동안 포인터가 참조하는 객체는 유효하게 유지해야합니다 (RAII 관용구를 사용하는 스마트 포인터는 문제를 해결합니다).


답변

예, std::vector사본을 저장합니다. vector물체의 예상 수명이 무엇인지 어떻게 알 수 있습니까?

객체의 소유권을 전송하거나 공유하려면 포인터를 사용하십시오 shared_ptr. 부스트 또는 TR1 과 같은 스마트 포인터는 리소스 관리를 용이하게합니다.


답변

C ++ 11부터 모든 표준 컨테이너 ( std::vector, std::map등)는 이동 의미론을 지원하므로 이제 rvalue를 표준 컨테이너에 전달하고 사본을 피할 수 있습니다.

// 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 ()을 사용하십시오. 다른 선택의 여지가 없습니다.