【问题标题】:Interaction of structs with object attributes and std::vector in c++c++中结构与对象属性和std::vector的交互
【发布时间】:2015-10-31 15:13:24
【问题描述】:

我遇到了这个问题,想知道是什么原因。

我的代码如下:

struct node{
  bool leaf;
  std::string label;
};

//in main
std::vector<node> graph;
graph.reserve(5);

现在,如果我尝试分配 graph[3].leaf = true;, 一切顺利。

但是,如果我尝试对对象类型执行相同的操作,例如 graphA[i].label = "01";, 我遇到了分段错误。

如果我将代码更改为

struct node{
  bool leaf;
  std::string * label;
};

并为向量中node 的每个实例中的字符串分配内存,我现在可以毫无问题地为graphA[i]-&gt;label 赋值。

这是为什么?任何回复将不胜感激。

【问题讨论】:

  • graph.reserve(5); => graph.resize(5); 应该修复它。你不需要指针和new
  • 尝试graph.at(3) 以获得更好的错误消息
  • reserve 只是保留,你的向量仍然有零个元素
  • @tobi303:如果异常离开main,则可能没有很好的错误消息。

标签: c++ vector segmentation-fault


【解决方案1】:

现在,如果我尝试分配 graph[3].leaf = true;

您正在调用未定义的行为。

graph 在索引 3 处没有元素。事实上,它根本没有元素。您只 reserved 内存 用于向量,但没有向其中添加任何元素。

您可以使用 resize 添加 5 个默认构造的元素:

graph.resize(5);

【讨论】:

    【解决方案2】:

    现在,如果我尝试分配 graph[3].leaf = true;,一切正常。

    需要强调的是,这仅仅是巧合。没有任何结果 - 你有未定义的行为,因为当graph 为空时你访问graph[3]。如果程序立即崩溃会更好,以便您发现有问题。

    graph 为空,因为您混淆了std::vectorreserveresize 成员函数。您没有将向量的元素计数设置为 5,您只是要求它为将来至少 5 个元素准备其内部保存的内存。 std::vector 甚至可以忽略这个请求。

    当您执行graphA[i].label = "01"; 时,当然还有未定义的行为。

    那么为什么第一个版本和指针“修复”(也调用未定义的行为)似乎工作正常,而另一个崩溃? C++ 作为一种编程语言不区分不同类型的未定义行为。 任何事情都有可能发生;您也可能会遇到第一次崩溃而第二次“解决”的情况。这就是未定义行为的本质。

    可能在实践中发生的情况是,在 boolstd::string* 的情况下,您巧合地写入程序允许写入的内存位置,因为您只是在处理使用单个 bool 或使用单个指针。在std::string 版本中,std::string 的所有自动动态内存管理都在幕后进行,涉及到内存中更多的地方,所以你碰巧碰到了一个被禁止的地方。

    但这只是一个非常投机的理论。如果您真的想确定,请调试代码并单步执行每个单独的操作。但请记住,未定义的行为始终是未定义的行为。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-11-13
      • 2011-05-06
      • 2010-09-19
      • 2017-09-05
      • 2018-06-06
      • 2011-05-24
      • 2012-06-30
      • 1970-01-01
      相关资源
      最近更新 更多