访问存储在向量中的指针的值

时间:2015-04-18 18:36:35

标签: c++ pointers vector struct

我试图创建一个三角形网格,以编写有限元分析的代码。我知道已经编写了这样的软件,但这是针对一个类项目的。

我尝试做的是将区域划分为均匀间隔的节点(网格点)。每个节点有6个连接到它的三角形,需要在计算中使用。为了简化操作,我创建了两个结构,一个用于节点,另一个用于三角形。

下面,我有一个最小的工作示例,说明了我在代码中尝试实现的内容。但是,此代码在将x,y值分配给顶点的行上接收分段错误。 gdb中产生的错误说明:

With using vectors (as per the minimum working example)
----------------------------
Program received signal SIGSEGV, Segmentation fault.
0x0000000000400f90 in std::vector<Node*, std::allocator<Node*> >::operator[] (this=0x0, __n=0)
    at /usr/include/c++/4.8/bits/stl_vector.h:771
771           { return *(this->_M_impl._M_start + __n); }

// Running backtrace
(gdb) bt
#0  0x0000000000400f90 in std::vector<Node*, std::allocator<Node*> >::operator[] (this=0x0, __n=0)
    at /usr/include/c++/4.8/bits/stl_vector.h:771
#1  0x0000000000400a87 in main () at minimumexample.cpp:28
----------------------------

而且我不确定如何解决这个问题。如果使用数组代替向量,会产生类似的错误,所以我不认为它只是向量类的问题吗?

With arrays instead of vectors
----------------------------
Program received signal SIGSEGV, Segmentation fault.
0x0000000000400929 in main () at minimumexample.cpp:28
28        MyGrid[0].Triangles[0]->vertex[0]->x = 0;

// Running backtrace
(gdb) bt
#0  0x0000000000400929 in main () at minimumexample.cpp:28
----------------------------

以下是我尝试做的最低工作示例。我不确定为什么我会出错,因为我根本无法看到我在向量中的界限。

#include <iostream>
#include <vector>

using namespace std;

struct Triangle;

struct Node
{
  double x; 
  double y;
  vector<Triangle*> Triangles;  
  Node() : Triangles(6) {}
};

struct Triangle
{
  vector<Node*> vertex;
  Triangle() : vertex(3) {} // 3 vertices per triangle
};

int main()
{
  int size = 10;
  vector<Node> MyGrid(size);
  double spacing = .25;

  // The below code should create 3 vertices of the triangle with the
  // three vertices of the triangle (x,y) defined as locations (0,0) for the 
  // first vertex, (1,0) for the second vertex, and (1,1) for the third.

  MyGrid[0].Triangles[0]->vertex[0]->x = 0; // Line 28: Error here
  MyGrid[0].Triangles[0]->vertex[0]->y = 0;
  MyGrid[0].Triangles[0]->vertex[1]->x = 1;
  MyGrid[0].Triangles[0]->vertex[1]->y = 0;
  MyGrid[0].Triangles[0]->vertex[2]->x = 1;
  MyGrid[0].Triangles[0]->vertex[2]->y = 1;

  return 0;
}

对于遇到此问题的任何其他人,这是代码的工作版本:

#include <iostream>
#include <vector>

using namespace std;

struct Triangle;

struct Node
{
  double x; 
  double y;
  Triangle *Triangles;  
};

struct Triangle
{
  Node *vertex;
};

int main()
{
  int size = 10;
  vector<Node> MyGrid(size);
  double spacing = .25;

  // Allocate 6 Triangle objects into the variable Triangles
  MyGrid[0].Triangles = new Triangle[6];
  // Allocate 3 nodes for Triangles[0]'s vertex
  MyGrid[0].Triangles[0].vertex = new Node[3];

  MyGrid[0].Triangles[0].vertex[0].x = 0; 
  MyGrid[0].Triangles[0].vertex[0].y = 0;
  MyGrid[0].Triangles[0].vertex[1].x = 1;
  MyGrid[0].Triangles[0].vertex[1].y = 0;
  MyGrid[0].Triangles[0].vertex[2].x = 1;
  MyGrid[0].Triangles[0].vertex[2].y = 1;

  return 0;
}

2 个答案:

答案 0 :(得分:1)

Node::Node

  vector<Triangle*> Triangles;  
  Node() : Triangles(6) {}

您只是将Triangles初始化为vector大小6。这不会为您提供有效的内存位置 - Triangle*中的Triangles需要使用new进行分配。

通常,您不需要vector<Triangle*>。只需使用vector<Triangle>代替。

答案 1 :(得分:0)

该程序的第二个版本避免了段错误,但没有解决 首先应该解决使用指针的问题。

首先,虽然这是您的问题的偶然因素, 我强烈建议写Triangle* triangles (注意小写t)而不是Triangle* Triangles,所以 triangles显然是变量名,而不是类名。

您现在遇到的问题是,如果您继续初始化 以这种方式MyGrid的其他元素,每一个 应该在顶点的三个Node个对象 您的一个网格三角形将创建 它自己的Triangle对象来覆盖那个三角形。你最终会得到 三个Triangle个对象,你只想要一个,而没有 Triangle将所有三个正确的Node个对象链接到它。 此外,Node中任何一个Node* vertex对象都没有 任何Triangle的数组都在原始vector<Node> MyGrid中, 并且它们都没有链接到任何Triangle(甚至链接的Triangle 对它而言,更不用说它应该有的六个Triangle*指针。

你所拥有的甚至不是网格的开头, 它注定是一个“岛屿”的集合,每个岛屿一个 MyGrid的成员,每个人都与其他成员完全隔离。

请注意,当您编写MyGrid[0].Triangles[0].vertex[0].x = 0时, 如果所有对象都正确地相互连接 MyGrid[0].Triangles[0].vertex[0]只是指向另一个Node的指针, 可能是MyGrid的成员(为什么要存储Node个对象 在其他任何地方?),所以更直接的方式来做同样的事情 要确定MyGrid这个成员,例如成员1, 然后写MyGrid[1].x = 0

实际上,像MyGrid[1].setCoordinates(0,0)这样设置两者 同时使用x和y坐标可以使您的程序更易于阅读 并且不太可能有错误。

更好的策略可能是更改NodeTriangle的定义 回到他们以前的样子, 但是这次,在你创建了Node个对象的向量之后, 为每个Node调用一个初始化其坐标的成员函数 (或者初始化Node的构造函数中的坐标 push_backvector<Node>; 然后开始创建Triangle个对象。对于您创建的每个Triangle, 对于Node应该连接的每个Triangle, 您需要在Triangle的{​​{1}}列表中插入triangle 您需要将Node插入Node的{​​{1}}列表中。 既然你总是成对地完成这些作业,那么拥有一个作品是值得的 两个函数调用。为了使事情更方便和 不容易出错, 函数被成员函数调用三次 vertex的{​​{1}}个参数,每个参数Triangle一个 Triangle将连接到。

如果这还不够清楚,请尝试绘制一些Node*的图表 对象和Node对象,指针箭头连接它们 他们应该联系的方式。无论你写什么都必须 创建一个数据结构,所有指针都正确链接。