如何在 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<std::string> 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++ 中随机分配给向量?的主要内容,如果未能解决你的问题,请参考以下文章