我是C ++的新手所以请耐心等待。
我做了一个看起来像这样的结构:
struct node{
double startPoint;
double endPoint;
vector<node*> children;
void addChild(node *aNode){
children.push_back(aNode);
}
void addPoints(double start, double end){
startPoint = start;
endPoint = end;
}
};
在我的计划中,我有以下内容:
vector<node*> data;
....
node *temp = (node*)malloc(sizeof(node));
temp->addPoints(lexical_cast<double>(numbers[0]), lexical_cast<double>(numbers[1]));
data[index]->addChild(temp);
其中“Index”是矢量数据的索引。 lexical_cast
内容正在将这些数字从字符串转换为双倍。
一切都有效,直到addChild(temp)
行。
终端吐了出来:
First-chance exception at 0x585b31ea (msvcr90d.dll) in Tree.exe: 0xC0000005: Access violation reading location 0xcdcdcdc1.
Unhandled exception at 0x585b31ea (msvcr90d.dll) in Tree.exe: 0xC0000005: Access violation reading location 0xcdcdcdc1.
但我不知道如何处理。
答案 0 :(得分:2)
malloc
分配一些空间,但不会在其中放置任何内容。它适用于普通旧数据结构(或简单的可初始化类),而在C语言中,这就是你所拥有的一切。
在C ++中,您有类,如std::vector
等,需要正确构造才能建立一些不变量。这是通过对具有自动存储持续时间的对象的直接声明来完成的,但对于动态分配的对象,您需要使用new
而不是malloc
。
例如,
std::vector<int> global; // (1)
void foo() {
std::vector<int> local; // (2)
std::vector<int> *bad = malloc(sizeof(*bad)); // (3)
std::vector<int> *good = new std::vector<int>; // (4)
std::unique_ptr<std::vector<int>> better(new std::vector<int>); (5)
}
foo
退出后立即销毁bad
来做任何事情,因为你调用的任何方法都会假设构造函数已经运行了,而且它没有
bad
。你不应该这样做,它只适用于你做自定义分配的聪明或棘手的事情。foo
有内存泄漏)现在,请注意您的node
类也有一个构造函数。在这种情况下,它是自动生成的,除了调用vector
构造函数之外什么都不做。不过,您需要调用它,这意味着使用new
动态分配node
。
所以,你的程序应该看起来更像:
std::vector<std::unique_ptr<node>> data;
...
std::unique_pre<node> temp(new node);
temp->addPoints(...);
data[index]->addChild(temp);
注意我假设data[index]
有效(我从addChild
看到您知道如何填充向量),并且unique_ptr
实施的单一所有者模型是合适的
答案 1 :(得分:1)
就我看到的代码而言,您永远不会将任何节点添加到data
数组
data.push_back(something);
因此访问data[index]
将超出阵列的已分配内存。在您尝试在该块中设置内存之前不会抱怨(通过addChild
尝试将元素推入children
数组)。
答案 2 :(得分:0)
node
而不是node*
,这样您就无需自行管理内存。 这是C ++,因此您不必为可以使用新节点的节点malloc空间如下:
Node * n = new Node();
New更好,因为它调用构造函数并分配空间,而malloc只执行后者。
您没有显示太多代码,但我会像这样重构节点类。
struct node{
double startPoint;
double endPoint;
vector<node> children;
node(){} //add default constrcutor
void addChild(node aNode){
children.push_back(aNode);
}
node & operator=(const node & n) {
startPoint = n.startPoint;
endPoint = n.endPoint;
return *this;
}
node(double start, double end): startPoint(start),endPoint(end){
} //in c++ you have constructors which this should have been in the first place
//constructors are used for initializing objects
};
nullptr
来避免代码中出现很多问题。你现在也有一个构造函数。现在您可以添加这样的节点。 node temp(start,end); data[index]=temp;
addPoints
应该是第一个使用在堆栈上分配内存而不使用new的编码样式称为RAII,是学习c ++和生成异常安全代码的重要技术,这是我提倡的不是主要原因存储
node*
的