无法在结构内填充矢量

Unable to populate vector inside struct

本文关键字:填充 结构      更新时间:2023-10-16

我是新手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);

其中"索引"是向量数据的索引。 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.

但我不知道如何处理这个问题。

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 用于任何操作,因为您调用的任何方法都将假定构造函数已经运行,并且它没有
    • 好的,如果不使用 Place new 显式构造它,则不能将 bad 用于任何内容。不过,您不应该这样做,它仅适用于使用自定义分配做聪明或棘手的事情的情况。
  4. 这没关系(但请注意,您必须手动删除它 - foo内存泄漏(
  5. 这更好 - 您无需手动清理

现在,请注意,您的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实现的单一所有者模型是合适的。

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

data.push_back(something);

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

  1. 我建议您在向量中存储node而不是node*,这样您就不必自己管理内存。
  2. 这是C++,因此您不必为可以使用 new 的节点 malloc 空间,如下所示:
    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. 更好的是,现在您无法传递添加子项nullptr从而避免了代码中的许多问题。您现在还有一个构造函数。现在您可以添加这样的节点。

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

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

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