Ner*_*igo 2 c++ indexing vector standard-library push-back
我正在研究一个使用矢量的程序.所以我做的第一件事是声明我的矢量.
std::vector<double> x;
x.reserve(10)
Run Code Online (Sandbox Code Playgroud)
(顺便说一句,这也被认为是不好的做法吗?我应该输入std::vector<double> x(10)吗?)
然后我继续为向量赋值,并询问它的大小.
for (int i=0; i<10; i++)
{
x[i]=7.1;
}
std::cout<<x.size()<<std::endl;
Run Code Online (Sandbox Code Playgroud)
我不知道它会返回0,所以经过一些搜索我发现我需要使用push_back方法而不是索引操作符.
for (int i=0; i<10; i++)
{
x.push_back(7.1);
}
std::cout<<x.size()<<std::endl;
Run Code Online (Sandbox Code Playgroud)
现在又回来了10.
所以我想知道的是为什么索引操作符允许我x在给定索引处访问向量中的"存储"值,但不会改变其大小.另外,为什么这是不好的做法?
当您这样做时,x.reserve(10)您只将容量设置为十个元素,但大小仍为零.
这意味着您在循环中使用索引运算符将超出范围(因为大小为零)并且您将具有未定义的行为.
如果你想设置大小,那么resize在构造向量时使用或者只是告诉它:
std::vector<double> x(10);
Run Code Online (Sandbox Code Playgroud)
至于矢量的容量,当你设置它(使用eg reserve)时,它会分配(在你的情况下)十个元素所需的内存.这意味着当你这样做时push_back,将不会重新分配矢量数据.
如果您不更改容量,或添加超出容量的元素,则每个元素都push_back可能导致重新分配矢量数据.
听起来你在问为什么事情是这样的。大部分都归结为效率。
如果x[i]在价值不存在的情况下创造价值,那么效率就会受到两次打击。首先,索引操作的调用者应确保索引不超过向量的当前大小。其次,即使您要为其分配新值,也需要默认构造新元素。
有reserve和的原因resize是相似的。resize需要每个元素的默认构造。对于这样的事情vector<double>似乎没什么大不了的,但对于vector<ComplicatedClass>,它确实可能是一件大事。Usingreserve是一种完全可选的优化,它允许您预测向量的最终大小并在它增长时防止重新分配。
push_back 避免元素的默认构造,因为内容是已知的,它可以使用移动或复制构造函数。
这都不是错误的风格,使用适合您情况的任何方式。