如何在 C++ 中随机分配给向量?

Posted

技术标签:

【中文标题】如何在 C++ 中随机分配给向量?【英文标题】:How to randomly assign to vector in C++? 【发布时间】:2012-11-13 19:06:44 【问题描述】:

我是 C++ 新手,经常被告知使用 std::vector 而不是 new[]

我正在尝试实现此功能,因为我知道向量的大小并希望随机(而不是按顺序)分配给它。

但是,当运行它时,我的程序终止并且没有错误输出,所以我很难过。

vector<string> v1;
v1.resize(2);
v1.insert(v1.begin() + 1, "world");
v1.insert(v1.begin() + 0, "world");

cout << v1.at(1) << endl;

【问题讨论】:

"arrays (just pointers)" 你这是什么意思?数组绝对不是“只是指针”。 @LightnessRacesinOrbit 我的意思是不要使用矢量<:mat>,而是使用 cv::Mat* 所以您的意思是指向动态分配的内存块的指针,该内存块大到足以容纳N 连续的cv::Mat 对象。 【参考方案1】:

别放弃,比那更容易

vector<string> v1(2);
v1[1] = "world";
v1[0] = "world";

cout << v1[1] << endl;

vector::insert 用于当您想要将项目添加到向量时,而不是当您想要替换已经存在的项目时,vector::insert 会改变向量的大小。

【讨论】:

感谢您的编辑,但我想发布与 OP 代码完全相同的内容。 如果类没有默认构造函数,你如何实现这一点,因为那样调整大小不起作用 @Aly:几乎所有的类都有一个默认构造函数。对于少数不这样做的人,只需将要复制的对象以及计数传递给构造函数即可。 std::vector&lt;std::string&gt; v1(2, "HI"); @MooingDuck 我包含的类是我自己的,是否有默认构造函数的做法(尽管如果默认构造的类没有意义,则使用此类)? @Aly:如果有一个默认构造函数没有意义,那就不要给它一个。没关系。不过,在使用调整大小功能时,您必须传递一个实例供 vector 复制。这很好。 v1.resize(4, "HI");【参考方案2】:

首先你调整它的大小,让它有两个空字符串:

"", ""

然后在begin() + 1 或第二个元素之前插入"world"

"", "world", ""

然后在begin() 或第一个元素之前插入"world"

"world", "", "world, ""

然后您使用v1.at(1) 访问第二个元素并获取空字符串。

大概,您不希望std::vector::insert 在现有元素之间插入新元素。您想像使用数组一样使用operator[]

vector<string> v1(2);
v1[1] = "world";
v1[0] = "world";
cout << v1.at(1) << endl;

【讨论】:

【参考方案3】:

随机分配

只需使用索引(显然,验证它是size)

v1[index] = value;

随机插入(验证该索引size)

v1.insert(v1.begin() + index, value);

按顺序在末尾插入/追加(不需要索引,您的值将插入到向量的末尾)

v1.push_back(value);

如果您打算插入许多值,请考虑在向量上调用reserve(),以便分配足够的内存来存储所有项目,否则当您插入数据时,随着向量的增长,您最终可能会进行多次重新分配

【讨论】:

+1,可能想改写 push_back 以追加与插入。对我来说,至少在语义和概念上似乎更准确 如果类没有默认构造函数,我不能调用 resize 对吗?在这种情况下,我如何拥有一定大小的向量并随机分配。还是我只需要创建一个空向量并继续插入? 确切地说,如果你的向量包含“对象”而不是“指向对象的指针”,那么每次向量增长时都会复制对象(这非常低效),考虑存储大对象的指针并复制对象的构造函数。 @Aly:您可以将要复制的对象传递给构造函数,或者在没有默认构造函数的类的情况下传递给 resize 函数。工作得很好。 @emartel:他问的不是副本的效率,也不是指针。他在问如何在没有默认构造函数的类上调整大小。【参考方案4】:

您的程序运行正常。您的错误在于代码的逻辑。

插入不会更改存储在索引 1 处的字符串。它会将字符串放在位置 1,并将 1 之后的所有索引向右移动。

开始第一个插入 第二个插入 ("","") -> ("", "world, "") -> ("world","","world","")

因此,当您打印 v1.at(1) 时,您正在打印一个空字符串。

要解决此问题,您需要使用:

v1.at(1)="world"
v1.at(0)="world"

--或--

v1[1] ="world"
v1[0] ="world"

这两个解决方案是等价的,但是第二个不会做任何边界检查。如果存在越界错误,第一个将引发错误。这无关紧要,只要您能保证您的索引永远不会越界。

【讨论】:

【参考方案5】:

正如许多人所说,您可以使用operator[] 重新分配旧值,因为您已经调整了向量的大小或用其他值填充了它。 如果您的数组将始终具有固定大小,您可以使用std::array,它应该会提供性能提升,但会牺牲调整数组大小或在运行时确定其大小的能力。

std::array<std::string,2> a1;
a1[0] = "world";
a1[1] = "world2";
std::cout<<a1.at(1)<<std::endl; //outputs world2

注意大小必须是静态的,所以不能这样:

int numStrings;
std::cin>>numStrings;
std::array<std::string,numStrings> a2; //ERROR

不幸的是,除了使用初始化列表之外,我认为没有任何方法可以在没有默认构造函数的情况下初始化 std::array

struct T

   T(std::string s):str(s) //no default constructor
   std::string str;

std::array<T,2> a3 = T(""), ""; //you can use a conversion constructor implicitly

显然,如果您想要一个包含大量对象的数组,这是不切实际的。

【讨论】:

以上是关于如何在 C++ 中随机分配给向量?的主要内容,如果未能解决你的问题,请参考以下文章

在 C++ 中,如何获取指向向量的指针?

C++ 的向量如何分配内存

如何通过将向量元素传递给函数来更改它们

如何在 Eigen (C++) 中处理复数?

C++:字符串向量的随机访问时间如何工作?

C++:如何安全地释放堆分配的向量数组?