【问题标题】:C++ vector of class objects and dynamic memory allocation类对象的 C++ 向量和动态内存分配
【发布时间】:2021-05-05 02:19:41
【问题描述】:

这是我想做的简化版本,它在调用 push_back 时崩溃,特别是在调用析构函数时。如果我删除析构函数的主体,它可以工作,但我想确保它被删除。我没有使用 calloc/free,而是尝试了 new/delete,结果相同。我在这里做错了什么?

#include <cstdlib>
#include <vector>


using namespace std;

class Buffer
{
public:
    float *DATA;

    Buffer(int length) {DATA = (float*) calloc (length,sizeof(float));};
    virtual ~Buffer(){free (DATA);};
    
private:
};

int main(int argc, char** argv)
{
    vector <Buffer> v;
    for (int i =0; i<10; i++)
        v.push_back(Buffer(1000));
    
    return 0;
}

【问题讨论】:

  • Buffer 不符合 rule-of-three。它需要。您对 DATA = buffer.DATA 的意图是什么?您意识到所做的只是将两个Buffer 对象DATA 成员连接到same 动态指针值?那么.. 谁真正拥有那个东西?我严重怀疑这是故意的,如果不是,最简单的方法:std::vector&lt;float&gt; DATA; 并扔掉其余的手动动态疯狂。
  • 感谢您的评论,我删除了复制构造函数,但问题仍然存在,错误是“double free or corruption (!prev)”
  • 那是因为默认的 copy-ctor 会完全完成你的工作。您是否阅读the link I provided 的页面,然后考虑它的重要性?考虑开头的句子:“如果一个类需要用户定义的析构函数、用户定义的复制构造函数或用户定义的复制赋值运算符,那么几乎可以肯定这三个都需要。” - 嗯,你有一个自定义的析构函数,所以你可能需要一个 proper 自定义的 copy-ctor 和 copy-assignment 操作符。
  • 谢谢,我做到了,我正在努力理解该信息,这并不明显,您能否为我的案例提供一个示例
  • 该链接有每个场景的示例。

标签: c++ class vector push-back


【解决方案1】:

这是一个工作代码:https://godbolt.org/z/ex9oMG。

#include <cstdlib>
#include <vector>

using namespace std;

class Buffer
{
public:
    float *DATA;

    Buffer(int length) {DATA = (float*) calloc (length,sizeof(float));};
    Buffer(const Buffer &buffer) = delete;
    Buffer(Buffer&& buffer) { 
        DATA = buffer.DATA;
        buffer.DATA = nullptr;
    }
    ~Buffer(){
        if (DATA) free(DATA);
    };
    
private:
};

int main(int argc, char** argv)
{
    vector <Buffer> v;
    for (int i =0; i<10; i++)
        v.push_back(Buffer(1000));
    return 0;
}

您需要在这里定义一个移动构造函数,主要是因为v.push_back(Buffer(1000)) 需要一个移动操作,否则删除原始副本会释放资源。

我已明确删除了复制 ctor,因为在处理此类资源时 - 不应允许复制。

【讨论】:

  • 重塑std::unique_ptr&lt;float[]&gt; 尽管vector&lt;Buffer&gt; v2; v2 = v; = no-joy ?为什么会有这样的限制? IE。 “在处理此类资源时 - 不应允许复制。” - 为什么??
  • @WhozCraig well OP 提出了他所面临的实际问题的“简化”版本——他不使用智能指针可能是有原因的。是否应该允许复制 - 好吧,在这种情况下,我们将处理重新发明std::shared_ptr&lt;float[]&gt;:/
  • 由于我们不知道它的用途是什么,我不相信一个简单的 std::vector&lt;float&gt; 和完全删除 Buffer 完全不适用于这个可能的 XY 的真正需求 X - 问题,尤其是考虑到在Buffer 中保留分配的幅度 甚至还没有完成;这本身就是一种重要的代码香气。
  • 如前所述,这是一个简化的示例,从用于处理卫星数据 (100 GB) 的 1000 行代码中提取。缓冲区包含实时读取/写入数据到DATA的函数,它还包含描述对象的各种其他变量......我猜我最初的错误是复制后没有删除引用,即“buffer.DATA = nullptr; ”。这是正确的吗?
  • @SVS 不完全是。您正在使用复制ctor。复制 ctor 并不意味着转移资源 - 那是移动 ctor 的角色。 buffer.DATA = nullptr 应该只是移动 ctor 的一部分。如果你真的想共享资源(DATA),你需要适当的资源所有权管理——类似于std::shared_ptr 所做的事情。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-02-03
  • 2015-01-20
  • 2014-06-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多