C++ 访问C+的成员+;用malloc分配的对象?

C++ 访问C+的成员+;用malloc分配的对象?,c++,malloc,C++,Malloc,[编者按:我编辑了这个标题,试图让它在将来对其他人有用。为了让回答者相信,当他们回答这个问题时,这只是一个“为什么不起作用?”的问题!] 以下代码在顶部->…行崩溃,并出现分段错误,无论节点*试图推送到向量子节点上的是什么。有人知道这可能是什么原因吗 struct Node { string data; struct Node* parent; vector<struct Node*> children; }; struct Node* push(strin

[编者按:我编辑了这个标题,试图让它在将来对其他人有用。为了让回答者相信,当他们回答这个问题时,这只是一个“为什么不起作用?”的问题!]

以下代码在
顶部->…
行崩溃,并出现分段错误,无论
节点*
试图推送到向量子节点上的是什么。有人知道这可能是什么原因吗

struct Node
{
    string data;
    struct Node* parent;
    vector<struct Node*> children;
};

struct Node* push(string word, struct Node* top)
{
    Node* temp = (struct Node*) malloc(sizeof(struct Node));
    temp -> data = word;
    temp -> parent = top;
    return temp;
}

int main()
{
    Node* top = push("blah", NULL);
    Node* temp = NULL;
    top -> children.push_back(temp);
}
struct节点
{
字符串数据;
结构节点*父节点;
媒介儿童;
};
结构节点*推送(字符串字,结构节点*顶部)
{
Node*temp=(struct Node*)malloc(sizeof(struct Node));
温度->数据=字;
temp->parent=top;
返回温度;
}
int main()
{
节点*top=push(“blah”,NULL);
节点*temp=NULL;
顶部->儿童。向后推(临时);
}

如果不在对象上使用
malloc
,则应使用
new
<代码> MaloC/是一个C函数,它只分配一块内存,而C++运算符<代码> STD::新的还负责您在这里错过的对象初始化和构造步骤,并导致您遇到麻烦(例如,对于<代码> TEMP->儿童< /代码>的构造函数,在您的情况下从未被调用过)。

作为经验法则:如果你写C++代码,你应该使用C++运算符<代码> STD::新< /COD>和 STD::删除< <代码> >动态内存分配和释放,而不是C函数。

< P>问题是MalOC/不会调用构造函数。你指望着要构造的向量
子对象

替换:

Node* temp = (struct Node*) malloc(sizeof(struct Node));
与:


malloc
(来自C)和
new
(来自C++)都将分配所需的内存,但只有
new
将调用所需的构造函数,因为C不使用它们。如果您不确定是否需要malloc,请使用new。

您的问题是您的
子向量未正确初始化。您应该使用
节点*temp=new节点
不要调用
malloc
节点的构造函数,它调用
子节点的构造函数,从而正确初始化
向量

malloc()只分配一个空内存块,而应该使用new()操作符初始化所有成员对象

Node* temp = new Node();

正如其他人所评论的,看起来你来自C,需要C++,而不仅仅是“C与<代码>类< /代码> ES”!p> 您的

push
函数看起来非常像一个构造函数。构造函数在分配了所需内存并执行必要的初始化后,由
new
调用。如果您不提供一个,编译器将为您生成一个(它还将提供一个复制构造函数和一个赋值运算符(请参阅)

由于您调用了
malloc()
而不是
new
,因此未调用合成的默认构造函数,因此未初始化
子对象
向量
,从而导致访问冲突

在这里,我将演示如何实现默认构造函数(并禁用其他两个),以启动
类的三个数据成员中的每一个(或
struct
):

#包括
#包括
使用std::vector;
使用std::string;
类节点
{
公众:
节点(常量字符串和单词,节点*顶部)
:数据(字)
,家长(上)
,儿童()
{
如果(顶部!=NULL)
{
顶部->儿童。向后推(此);
}
}
虚拟节点()
{
std::vector::iterator i=std::find(children.begin(),children.end(),this);
如果(i!=children.end())
{
父->子对象。删除(i);
}
//托多:你可能希望在这一点上毁掉孩子们
}
私人:
节点(常量节点&禁用);
节点和运算符=(常量节点和禁用);
私人:
字符串数据;
节点*父节点;
媒介儿童;
};
int main()
{
节点顶部(“blah”,NULL);
节点子节点(“foo”、&top);
}

我还实现了一个析构函数,它可以在销毁时从父节点的子节点中删除节点。

什么是
top
类型,它是否指向某个对象?请给出一个初始化top的完整示例。您可以将空指针推入向量,但
top
需要指向有效的内存区域n,否则坏的事情发生了。除了代码之外,代码中的“代码> >顶部/代码>在哪里,除了在没有声明的情况下,在代码中提到一次?主代码< /代码>……不像C,不需要在C++中代码<节点**/COD>之前键入<代码>结构>代码>。Eu> <代码>节点 .V.VANCARGEN:听起来你来自C背景。注意C++与C非常不同,实际上是被认为是非常不同的语言。我建议拿起。你可能不需要从入门书开始,但它当然不会伤害。我否决了你,因为我错了。你应该是错的——很大程度上是因为你没有解释它们为什么不同(在答案的最初版本中,这只是第一句话)。然后我又四处看了看,意识到我错了,你是对的,于是取消了否决票——尽管我没有投赞成票,因为最初的版本仍然是一个糟糕的答案。现在你添加了一个很好的解释,我投了赞成票。没有
std::new
std::delete
new
delete甚至不是函数(也不是运算符);它们是语言构造。
Node* temp = new Node();
#include <string>
#include <vector>
using std::vector;
using std::string;

class Node
{
public:
    Node(const string& word, Node* top)
        :data(word)
        ,parent(top)
        ,children()
    {
        if (top != NULL)
        {
            top->children.push_back(this);
        }
    }

    virtual ~Node()
    {
        std::vector<Node*>::iterator i = std::find(children.begin(), children.end(), this);
        if (i != children.end())
        {
            parent->children.erase(i);
        }
        // TODO: You may wish to destory children at this point
    }

private:
    Node(const Node& disable);
    Node& operator =(const Node& disable);

private:
    string data;
    Node* parent;
    vector<Node*> children;
};

int main()
{
    Node top("blah", NULL);
    Node child("foo", &top);
}