【问题标题】:std::vector memory allocation issuestd::vector 内存分配问题
【发布时间】:2013-09-20 09:44:15
【问题描述】:

我在尝试删除指针向量时遇到问题:

std::vector<float*> *v;

v = new std::vector<float*>;
v->assign(2, new float[2]);

for (int i = 0; i < 2; ++i)
{
    delete[] v->at(i);
}
delete v;

我正在从整个向量中删除每个元素,但我仍然得到一个断言。你能告诉我我做错了什么吗?

提前谢谢你。

【问题讨论】:

  • 你得到了什么断言?
  • 这是断言:表达式:_BLOCK_TYPE_IS_VALID(pHead->nBlockUse)

标签: c++ memory memory-management stl stdvector


【解决方案1】:

这并不像你认为的那样:

v->assign(2, new float[2]);

分配一个大小为 2 的数组,然后将两个指向它的指针存储在 vector 中。当你delete时,同一个指针会被删除两次。

如果你想要一个多维数组,你可以试试std::vector&lt; std::array&lt; float, 2 &gt; &gt;。自己做newdelete 是一种代码味道。 (new vector … 也是如此;这可能不是您真正想要的。)

【讨论】:

  • new vector 没有指向std::vector
  • 是的,但是为什么你需要一个指向向量的指针而不仅仅是一个向量呢?
  • @user1917028:C++ 倾向于值语义;所以你应该有一个很好的理由来创建一个指向向量的原始指针。假设您真的想这样做,您可以考虑使用 smart 指针,如 std::shared_ptrstd::unique_ptr
【解决方案2】:

v-&gt;assign(2, new float[2]) 的作用与:

float *f = new float[2];
for(int i = 0; i < 2; i++)
   v->push_back(f);

当然,这很可能不是你想要的——你可能想要:

for(int i = 0; i < 2; i++)
{
   float *f = new float[2];
   v->push_back(f);
}

vector 上使用new 是完全错误的——只需使用普通向量即可。在里面放一个vector&lt;float&gt; - 或者,如果你每次只想要两个元素,使用类似的东西:

struct f2 { float a; float b; };
vector<struct f2> v;

【讨论】:

    【解决方案3】:

    一般来说,拥有原始 拥有指针并不是一个好主意(除非在特殊情况下,例如当您定义一些自定义的高性能高度专业化的数据结构时)。

    在您的代码中 - 除非您处于特殊情况 - 在现代 C++11/14 中,不应显式调用 newdelete

    您的代码示例风格看起来更像 Java 和其他基于垃圾收集的基于引用语义的语言风格。相反,C++ 更倾向于值语义(例如,更喜欢:MyClass x;MyClass * px = new MyClass();,如果你真的需要一些 拥有 指针,请使用 智能指针 喜欢std::shared_ptrstd::unique_ptr):

    // Your original code:
    //
    //   std::vector<float*> *v;
    //   v = new std::vector<float*>;
    //
    // Not good, since:
    // 
    // 1. You have a std::vector of owning pointers
    //    (std::vector<float *>)
    //
    // 2. You have a raw owning pointer for the containing std::vector itself
    //    (v = new std::vector<....>)
    //
    

    编写代码的更现代和正确的方法是使用vectors 的vector(而不是原始拥有指针float*vector):

    //
    // Vector of vectors (i.e. 2D matrix), allocated on the stack
    // Note: no raw owning pointers here.
    //
    vector<vector<float>> v;
    

    然后您可以使用std::vector::push_back() 或其他一些std::vector 方法来填充向量。


    作为 2D 矩阵的更高性能和更少开销的替代方案,您可以使用单个 1D std::vector,并将 2D 矩阵的内容线性化单个 一维连续向量,大小为Rows * Columns,例如:

    vector<float> matrix;
    matrix.resize( Rows * Columns );
    

    要访问位置 (rowIndex, columnIndex) 的元素,您可以使用这样的公式(如果您按行存储矩阵元素,即 row#1row#2 em>, ..., row#N):

    indexInVector = columnIndex + rowIndex * Columns;
    

    所有这些都可以很好地包装在类模板template &lt;typename T&gt; class Matrix {...}; 中,具有读写矩阵元素的适当方法,并包含std::vector&lt;T&gt; 作为数据成员。

    【讨论】:

      猜你喜欢
      • 2015-04-08
      • 1970-01-01
      • 2011-01-19
      • 1970-01-01
      • 2020-10-11
      • 1970-01-01
      • 1970-01-01
      • 2012-10-08
      • 2015-09-24
      相关资源
      最近更新 更多