为什么要使用 C++ 'vector' 的新调用?

Why use a new call with a C++ 'vector'?

代码 vector<someType> myVector; 动态分配内存,因此存储的任何元素都将存在,直到 delete 被调用。那么下面的 vector<someType> *myVector = new vector<someType>(); 与前面的有什么不同(除了是指针)?

这里是否发生了双重分配? 每个人都提到混合 vectornew 调用是邪恶的,但为什么呢?如果它是邪恶的,为什么它是编译器可接受的代码,什么时候可以使用?

Is there a double allocation happening here?

取决于你所说的 "double allocation" 的意思。

您正在使用动态内存分配为 std::vector 分配内存。 std::vector 的构造函数对 std::vector 的元素做同样的事情。如果这就是你所说的 "double allocation" 的意思,那么答案就是 "Yes".

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

使用

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

暗示您负责为 myVector 管理动态分配的内存。这引入了一些陷阱:

  1. new vector<someType>() 可以抛出 std::bad_alloc。您必须添加代码来处理异常。如果不这样做,您最终将终止您的应用程序。

  2. 您必须确保释放内存。如果不这样做,您的程序就会泄漏内存。

  3. 您必须确保在释放内存后不使用指针。

这些并不完全是邪恶,但您在应用程序代码中添加了不必要的工作。

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

如果您的应用程序出于对您有意义的原因在某些核心组件中管理低级数据,则使用动态分配的 std::vector 是可以接受的。我认为将此类代码散布在您的代码库中是不可接受的。显然,这是我的意见。 YMMV.

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

没有。当此对象不再可用时,此内存将被删除。

考虑以下几点:

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

    // Do a lot of operations on this vector

}

此范围结束后,v 将被删除 (RAII)。所以它分配的内存自动释放了

但是

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

    // Do a lot of operations on this vector

}

此范围结束后,v 对象不会被删除,直到您显式调用 delete v

比指针更好的方法是使用 shared_ptrunique_ptrweak_ptr,这样可以避免忘记使用 delete

你的第一个陈述是不正确的。 vector<someType> myVector 中的元素将一直存在,直到 vector 被销毁。如果 vector<someType> 是一个局部变量,它会在超出范围时自动销毁。您不需要显式调用 delete。如果您考虑到由于可能抛出的异常,您的 delete 语句可能永远不会到达,从而导致内存泄漏,那么显式调用 delete 很容易出错。 例如。比较以下两种情况

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.
}

除此之外,向量确实会动态分配内存来存储新元素。两种情况的区别是:

  • std::vector<int> v v 是栈上的一个对象,动态分配内存以存储元素。

  • std::vector<int>* v = new std::vector<int> v 是指向动态分配对象的指针,该对象动态分配内存以存储元素。如前所述,您需要显式调用 delete 来销毁此对象。