C ++将字符串放入字符串向量的结构中

时间:2016-09-01 13:40:03

标签: c++ string vector

我在将字符串值放入“字符串向量结构”时遇到问题。 最简单的可重现代码如下:

#include <vector>
#include <string>
#include <iostream>

using namespace std;

struct ttt {
  string name;
  unsigned int ID;
  vector<unsigned int> numList;
};

int main() {
  vector<ttt> b;
  b.reserve(3);
  b[0].ID = 1;
  b[0].numList.push_back(3);
  b[0].numList.push_back(4);
  string dd ("Desk");
  b[0].name = dd;
  cout << b[0].ID << b[0].name << b[0].numList[2] << endl;

  return 0;
}

代码编译,但无法将“Desk”字符串放入b [0] .name,一个结构元素。分段故障在现场出现。

我也试过以下几行,但都失败了。

b[0].name.push_back(dd);
b[0].name += dd;

我的编译器是GCC g ++ 4.7.7 20120313, 我用下面的编译命令。

/usr/bin/g++ --std=gnu++0x -Werror -Wall -Wextra -Warray-bounds

真诚地感谢任何帮助。

4 个答案:

答案 0 :(得分:2)

有两个错误:

直接分配b[0]而不调用push_back或不事先在构造函数调用中初始化它。

另一条违规行

b[0].numList[2]

因为您只调用了push_back()两次,并且索引是从0开始的。

像这样直接初始化矢量会好得多:

#include <string>
#include <vector>
#include <iostream>

using namespace std;

struct ttt {
  string name;
  unsigned int ID;
  vector<unsigned int> numList;
};

int main() {
  vector<ttt> b{{"Desk", 1, { 3, 4 }}};
  cout << b[0].ID << b[0].name << b[0].numList[1] << endl;
}

Live Example

答案 1 :(得分:1)

您可能不会使用下标运算符为空向量分配新值。请改为使用push_back成员函数。

例如

std::vector<ttt> b;
b.reserve( 3 );

//...

b.push_back( ttt() );
b.back().ID = 1;
//...

答案 2 :(得分:0)

Valgrind在该代码上报告的第一个错误是

==28307== Conditional jump or move depends on uninitialised value(s)
==28307==    at 0x40154F: void std::vector<unsigned int, std::allocator<unsigned int> >::emplace_back<unsigned int>(unsigned int&&) (vector.tcc:94)
==28307==    by 0x4012D7: std::vector<unsigned int, std::allocator<unsigned int> >::push_back(unsigned int&&) (stl_vector.h:933)
==28307==    by 0x400F00: main (39273136.cpp:17)

虽然这看起来有点神秘,但有些经验表明要检查this push_back()的{​​{1}}参数是否已初始化。仔细查看代码,我们看到:

  vector<ttt> b;
  b.reserve(3);
  b[0].ID = 1;
  b[0].numList.push_back(3);

你已经告诉向量准备有3个元素,但是你永远不会向它添加任何ttt个对象。当您访问b[0]时,您正在使用未初始化的内存(Valgrind并未抱怨对b[0].ID的分配,因为内存已分配并属于b - 但调用{{1}尝试读取可能是随机垃圾的push_back成员。

显而易见的解决方案是vector(或以其他方式创建)emplace_back()的元素。

答案 3 :(得分:0)

当您在向量上调用reserve()时,它不会创建所包含类型的任何实例。 它只为元素分配空间。。因此,当您尝试访问向量中的这些位置时,您将获得未定义的行为。您必须首先将元素推入向量中,或者在尝试对其进行任何读取或写入之前,使用vector<ttt> b(6);之类的调用对其进行零初始化。

仅编辑声明ttt向量的一行并删除reserve()调用修复此程序。

另外要注意,因为您尝试访问b[0].numList[2]第三个​​元素,但您只为两个元素执行了push_back

#include <vector>
#include <string>
#include <iostream>

using namespace std;

struct ttt {
  string name;
  unsigned int ID;
  vector<unsigned int> numList;
};

int main() {
  vector<ttt> b(3); //create 3 zero-init elements in vector b
  b[0].ID = 1;
  b[0].numList.push_back(3);
  b[0].numList.push_back(4);
  string dd ("Desk");
  b[0].name = dd;
  cout << b[0].ID << b[0].name << b[0].numList[2] << endl;
                                             //^beware, this hasn't been initialized
  return 0;
}

输出:1Desk0