4

我是 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.

但我不知道如何处理。

4

3 回答 3

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)
}
  1. 很好 - 这个全局被自动初始化(我的意思是调用构造函数)
  2. 很好 - 这个局部变量也是自动构造的,并在foo退出后立即正确销毁
  3. 你不能bad用于任何事情,因为你调用的任何方法都会假设构造函数已经运行,但它没有
    • 好的,如果不使用Placement new 显式构造它,您将无法使用bad任何东西。你不应该这样做,它只适用于你用自定义分配做聪明或棘手的事情。
  4. 这没关系(但请注意,您必须手动删除它 -foo有内存泄漏)
  5. 这更好 - 你不需要手动清理

现在,请注意您的node有一个构造函数。vector在这种情况下,它是自动生成的,除了调用构造函数之外什么都不做。尽管如此,您仍需要调用它,这意味着使用newfor 动态分配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是合适的。

于 2013-08-07T20:19:03.513 回答
1

就我看到的代码而言,您永远不会将任何节点添加到data数组中

data.push_back(something);

因此访问data[index]将超出数组的分配内存。addChild除非您尝试在该块中设置内存(通过尝试将元素推入children数组),否则它不会抱怨。

于 2013-08-07T20:08:32.580 回答
0
  1. 我建议您将 anode而不是 a存储node*在向量中,这样您就不必自己管理内存。
  2. 这是 C++,因此您不必为可以使用 new 的节点分配空间,如下所示:
    Node * n = new Node();

  3. 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
};  
  1. 更好的是,现在您不能通过 add childnullptr避免代码中出现很多问题。你现在也有一个构造函数。现在你可以像这样添加一个节点。

node temp(start,end); data[index]=temp;

  1. 你现在有一个构造函数,它addPoints应该放在首位
  2. 我还做了一个赋值运算符

使用在堆栈上分配内存而不使用 new 的编码风格称为RAIInode* ,是学习 c++ 和生成异常安全代码的重要技术,这是我提倡不存储's 的主要原因

于 2013-08-07T20:06:21.197 回答