Why use a new call with c++ vector?

…衆ロ難τιáo~ 提交于 2021-02-07 10:33:16

问题


The code vector<someType> myVector; dynamically allocates memory, so any elements stored will live until a delete is called. So how is the following, vector<someType> *myVector = new vector<someType>();, different (other than being a pointer) from the earlier one?

Is there a double allocation happening here? Everyone mentions it is evil to mix a vector with a new call, but why? If it is evil, why is it acceptable code for the compiler and when is it okay to use?


回答1:


Your first statement is not true. The elements in vector<someType> myVector will live until the vector is destroyed. If vector<someType> is a local variable, it will be destroyed automatically when it goes out of scope. You don't need to call delete explicitly. Calling delete explicitly is error-prone if you take into account that because of exceptions that might be thrown, your delete statement may never be reached, leading to memory leaks. E.g. compare the following two cases

void foo()
{
   std::vector<int> v;
   v.push_back(1);
   f(); // f is some operation that might throw exception.
}  // v is automatically destroyed even if f throws.

void bar()
{
   std::vector<int>* v = new std::vector<int>;
   v->push_back(1);
   f(); // f is some operation that might throw exception.
   delete v;  // You need to call delete explicitly here.
              // The vector will be destroyed only if f doesn't throw.
}

Apart from the above, it's true that a vector dynamically allocates memory to store new elements. The difference between the two cases is:

  • std::vector<int> v v is an object on the stack, that dynamically allocates memory in order to store elements.

  • std::vector<int>* v = new std::vector<int> v is a pointer to a dynamically allocated object, that dynamically allocates memory in order to store elements. As said already, you need to explictly call delete to destroy this object.




回答2:


Is there a double allocation happening here?

Depends on what you mean by "double allocation".

You are allocating memory for the std::vector using dynamic memory allocation. The constructor of std::vector does the same thing for the elements of the std::vector. If that is what you mean by "double allocation", then the answer is "Yes".

Everyone mentions it is evil to mix a vector with a new call, but why?

Use of

vector<someType> *myVector = new vector<someType>();

implies that you are taking responsibility of managing dynamically allocated memory for myVector. That introduces some pitfalls:

  1. new vector<someType>() can throw std::bad_alloc. You'll have to add code to deal with the exception. If you don't, you will end up terminating your application.

  2. You have to make sure that you deallocate the memory. If you don't, your program leaks memory.

  3. You have to make sure that you don't use the pointer after the memory has been deallocated.

These are not exactly evil but you add more work in your application code than is necessary.

If it is evil, why is it acceptable code for the compiler and when is it okay to use?

If you have an application where you are managing low level data in some core components for reasons that make sense to you, it's acceptable to use dynamically allocated std::vector. I think it's unacceptable to have such code strewn all over your code base. That's my opinion, obviously. YMMV.




回答3:


The code vector<someType> myVector; dynamically allocates memory, so any elements stored will live until a delete is called

No. This memory will be deleted when this object is no more available.

Consider the following:

{
    // Allocate a vector of 4 ints
    vector<int> v(4);

    // Do a lot of operations on this vector

}

After this scope ends, v will be deleted (RAII). So the memory allocated by it is automatically freed.

But

{
    // Allocate a vector of 4 ints
    vector<int> *v = new vector<int>(4);

    // Do a lot of operations on this vector

}

After this scope ends, the v object isn't deleted, until you call delete v explicitly.

For a better approach than pointers to make your object escape the scope, is to use shared_ptr, unique_ptr, and weak_ptr, this will keep you safe from forgetting using delete



来源:https://stackoverflow.com/questions/48757030/why-use-a-new-call-with-c-vector

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!