0

我是 C/C++ 新手并正在开发 C++ 应用程序。我对 new 和 malloc 有疑问。我的应用程序有点复杂,而且还有一些 C 结构。在某些时候,我想为 MyData 类型的类(包含双端队列)分配新内存,后来我将该指针分配给 C 结构中的指针。我的代码的较小版本如下。

#include <deque>
class MyData 
{
public:
    MyData(){};
    ~MyData() {};

    std::deque<int>& GetDequeMyDataSet() {return deque_MyDataSet; };

private:
    std::deque<int>     deque_MyDataSet;//contains ohlc data for the symbol   
};

int _tmain(int argc, _TCHAR* argv[])
{
    MyData* pMyData = new MyData();
    MyData* p_Data = (MyData*)malloc(sizeof(MyData*));
    p_Data = pMyData;
    p_Data->GetDequeMyDataSet().push_back(10);
    p_Data->GetDequeMyDataSet().push_back(11);
    //.... Several other push back and operations releated to this deque goes here. 
    delete pMyData;// At the end I free both memories.
    free(p_Data);
    return 0;
}

在为两个指针分配内存后,我在 malloc 指针 (p_Data) 上使用了 GetDequeMyDataSet() 方法。我的问题是是否可以将项目 push_back 到这个 malloc 指针上的双端队列,因为我只为指针分配了内存?malloc 可以处理双端队列的动态内存分配吗?

4

6 回答 6

6

简而言之,这是您的情况:

void * p = malloc(1);
void * q = malloc(1);

q = p;

free(q);
free(p);

你能发现问题吗?

于 2013-02-25T11:42:36.460 回答
2

如果您主要是 push_back 元素,则使用 deque 毫无意义。与向量插入相比,它在推回元素时速度较慢,而在 push_front 中速度更快。同样使用 malloc 只是在问问题。新的也是如此,如果您确实需要动态分配您的类对象,请使用 std::shared_ptr 或 std::unique_ptr 。他们会为你处理内存释放。

 #include <vector>

 class MyData 
 {
 public:
     MyData() {};
     ~MyData() {};
     std::vector<int>& GetMyDataSet() { return m_myDataSet; }
 private:
     std::vector<int> m_myDataSet;
 };

 int _tmain(int argc, _TCHAR* argv[])
 {
     MyData myData;
     myData.GetMyDataSet().push_back(10);

     //or dynamically
     auto pMyData = std::make_shared<MyData>();
     pMyData->GetMyDataSet().push_back(10);


     return 0;
 }
于 2013-02-25T12:05:45.060 回答
0

malloc 和 new 之间的区别在于前者不调用类的构造函数,而后者调用。构造函数依次调用成员变量的构造函数,就像deque_MyDataSet在这种情况下一样。所以你所做的不会调用双端队列的构造函数。

始终使用 new inC++以避免以后出现问题。并确保一切都正确初始化。

于 2013-02-25T11:43:22.860 回答
0

混合malloc()new是一个坏主意。另外,什么是“C类”?

无论如何,这个:

MyData* p_Data = (MyData*)malloc(sizeof(MyData*));

完全错误,您没有分配正确的内存量。你的意思是:

MyData* p_Data = (MyData *) malloc(sizeof *p_Data);

因为您必须具有MyData所指向的结构的实际大小。您的代码只为指针分配了足够的空间,这不是您的意思。

请注意,强制转换在 C++ 中是必需的,但在 C 中是不好的做法

于 2013-02-25T11:45:02.177 回答
0

我的问题是是否可以 push_back 项目以在这个 malloc 指针上进行双端队列,因为它只为指针分配了内存?

通常,无论它是如何初始化的(动态分配或在堆栈上),都可以将项目 push_back 到对象中。虽然在这种情况下,p_Data已分配,但根本没有初始化。

要看到这一点,您需要了解 malloc 和 new 之间的区别:

malloc 是 C 函数,它分配一块内存并返回一个 (void) 指向它的指针。它存在于 C++ 中的原因是因为 C++ 最初与 C 兼容并且能够使用它的库(现在它是向后兼容所必需的。

new 是 C++ 运算符,它分配一块内存,将其解释为一个对象,并透明地调用该对象的构造函数。这两个功能不可互换。

为对象分配内存时,请始终使用 new。malloc 不会调用对象的构造函数(也不会自由调用对象的析构函数)。

等效代码:

class MyData { /* same as in your question */ };

// 1: normal C++ dynamic object allocation
MyData* pMyData = new MyData();

// 2: allocate through malloc and call constructor through placement new 
void*   block = (MyData*)malloc(sizeof(MyData)); // allocate sizeof(MyData) bytes
MyData* pMyData = new(block) MyData(); // call constructor on block memory

这意味着如果您使用 malloc 和 free,您的对象不会被初始化,即使您通常(直观地)期望它们是这样的。

TL:DR:永远不要在 C++ 中使用 malloc 和 free。

在为两个指针分配内存后,我在 malloc 指针(p_Data)上使用了 GetDequeMyDataSet() 方法

那不应该奏效。不应初始化 malloc 的指针(分配是,初始化否)。

最重要的是,由于您 assign p_Data = pMyData;,您对 free 的调用将尝试释放已由 delete 语句分配的内存(因为两者都指向相同的地址)。

这应该被视为访问冲突错误。

于 2013-02-25T12:10:58.533 回答
0

在 C++ 中,通常不需要动态分配东西。您只需在需要时创建一个新对象:

int _tmain(int argc, _TCHAR* argv[])
{
    MyData myData;   // No pointers, no new

    MyData* p_Data = &myData;   // Create a pointer to myData, if you need one
    p_Data->GetDequeMyDataSet().push_back(10);
    p_Data->GetDequeMyDataSet().push_back(11);
    //.... Several other push back and operations releated to this deque goes here. 

    // Nothing to delete or free here

    return 0;
}
于 2013-02-25T12:12:41.573 回答