在C++中动态分配向量的安全方法是什么?

3
在动态分配结构体后,我认为在最后加上“delete”是明智的。但这会导致运行时错误。虽然编译通过,但如果我去掉“delete”,它可以正常运行。但我担心可能会有内存泄漏。如何安全地处理这段代码?
#include <iostream>
#include <vector>
using namespace std;

typedef struct
{
    vector<char*> vstr;
    vector<int> vint;

}VecStrInt;

int main()
{
    VecStrInt * mtx = new VecStrInt();

    mtx[0].vstr.push_back("Hello");
    mtx[0].vint.push_back(1);

    cout<<mtx[0].vint.at(0)<<endl;
    cout<<mtx[0].vstr.at(0)<<endl;

    //delete [] mtx;

    return 0;
}

顺便说一句,你可以完全避免使用new,std::vector<VecStrInt> mtx; 或者 VecStrInt mtx; 都足够了(取决于你想要什么)。 - Jarod42
3个回答

6
delete[]的调用与delete的调用不同(请注意方括号)。
您需要将deletenew配对,将delete[]new SomeType[someCount]配对。
在您的情况下,您分配了一个单独的对象,而不是数组。您的对象恰好代表向量,这是一个数组,但对于C++来说并不重要:您使用“单个”new进行了分配,因此无法对其应用“数组”delete[]
因此,您需要使用常规的删除运算符delete来删除它:
delete mtx;

注意:很少有情况需要动态分配std::vector<T>。代表std::vector<T>的对象本身非常小,数据存储在其他地方,并且是动态分配的。因此,您可以使用该对象。
VecStrInt mtx;

跳过删除操作。


1
如果您只分配了一个对象,那么您必须使用delete运算符。
VecStrInt * mtx = new VecStrInt();
//...
delete mtx;

如果您分配了一个对象数组(即使数组只包含一个元素),您必须使用 delete[] 运算符,像这样:

VecStrInt * mtx = new VecStrInt[1];
//...
delete [] mtx;

同时您还可以使用标准智能指针,例如std::unique_ptr


0

如果你真的想要安全,就不应该像这样直接使用new/delete,因为在函数执行过程中可能会抛出异常,导致delete语句无法执行。

C++分配和释放内存的方式是通过构造函数/析构函数完成的,称为RAII。标准类通过它们的构造函数/析构函数来处理这个问题。例如:

  • 使用标准容器如std::vector<T>来代替T* = new T[]来处理多个元素
  • 使用std::string来处理字符串,而不是使用char*
  • 对于更复杂的情况,可以使用C++11标准引入的智能指针:std::unique_ptr<T>std::shared_ptr<T>/std::weak_ptr<T>

注意:在您的情况下,mtx仅在main函数内使用,因此您不需要在堆上分配它,您可以直接编写:

int main()
{
    VecStrInt mtx;

    mtx.vstr.push_back("Hello");
    mtx.vint.push_back(1);

    cout << mtx.vint.at(0) << endl;
    cout << mtx.vstr.at(0) << endl;

    return 0;
}

同样地,在VecStrInt中,应该使用std::string而不是char*,以避免字符串内存泄漏。
#include <string>

struct VecStrInt
{
    vector<string> vstr;
    vector<int> vint;
};

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接