我正在开发一个使用矢量的程序。所以我做的第一件事是声明我的矢量。
std::vector<double> x;
x.reserve(10)
(顺便说一下,这也被认为是不好的做法吗?我应该只输入std::vector<double> x(10)
吗?)
然后我继续为矢量赋值,并询问它的大小。
for (int i=0; i<10; i++)
{
x[i]=7.1;
}
std::cout<<x.size()<<std::endl;
我不知道它会返回0
,所以经过一些搜索我发现我需要使用push_back方法而不是索引操作符。
for (int i=0; i<10; i++)
{
x.push_back(7.1);
}
std::cout<<x.size()<<std::endl;
现在它返回10
。
所以我想知道的是为什么索引操作符允许我访问值&#34;存储&#34;在给定索引处的向量x
中,但不会更改其大小。另外,为什么这是不好的做法?
答案 0 :(得分:5)
执行x.reserve(10)
时,只将容量设置为10个元素,但 size 仍为零。
这意味着你在循环中使用索引运算符将超出界限(因为大小为零)并且你将有未定义的行为。
如果您想设置大小,请使用resize
或在构造向量时告诉它:
std::vector<double> x(10);
对于向量的容量,当你设置它时(使用例如reserve
),它会分配(在你的情况下)十个元素所需的内存。这意味着当你执行push_back
时,将不会重新分配矢量数据。
如果您不更改容量或添加超出容量的元素,则每个push_back
可能会导致重新分配矢量数据。
答案 1 :(得分:2)
顺便说一下,这也被认为是不好的做法吗?std::vector<double> x; x.reserve(10)
不,创建一个空向量并保留内存并不是一个坏习惯。
我应该输入
std::vector<double> (10)
吗?)
如果你的目的是初始化10个元素的向量,而不是空元素,那么你应该这样做。 (如果你的目的是创建一个空矢量,那么没有)
然后我继续为矢量赋值,并询问它的大小。
for (int i=0; i<10; i++) { x[i]=7.1;
这有未定义的行为。不要尝试访问不存在的对象。
所以经过一些搜索我发现我需要使用push_back方法而不是索引操作符。
这是一个选择。另一种方法是使用构造函数初始化元素:std::vector<double> (10)
。另一个是使用std::vector::resize
。
为什么在C ++中对向量使用索引运算符会被认为是不好的样式?
这不是一般的。如果您尝试访问的索引中没有元素,那么这是错误的(不仅仅是错误的样式)。
答案 2 :(得分:1)
我应该输入
std::vector<double> x(10)
吗?
肯定是的!
如@Some programmer dude's answer std::vector::reserve()
中所述,仅影响分配政策,但不影响向量的大小。
std::vector<double> x(10);
实际上相当于
std::vector<double> x;
x.resize(10);
答案 3 :(得分:1)
听起来你真的在问为什么事情是这样的。其中大部分都取决于效率。
如果x[i]
创建了一个值,如果它还没有存在,那么效率会有两个点击。首先,每个索引操作都需要包含一个检查,以查看它是否超出了向量的当前大小。其次,即使您要为其分配新值,新元素也需要默认构建。
同时拥有reserve
和resize
的原因相似。 resize
需要每个元素的默认构造。对于像vector<double>
这样看起来不是什么大不了的事,但对于vector<ComplicatedClass>
来说,这确实是一件大事。使用reserve
是一种完全可选的优化,它允许您预测矢量的最终大小,并防止重新分配的增长。
push_back
避免了元素的默认构造,因为已知内容可以使用移动或复制构造函数。
这些都不是坏的风格,根据你的情况使用适合的任何东西。
答案 4 :(得分:0)
std::vector
的括号运算符可让您访问向量中索引i
的项目。如果项目i
不存在,则无法访问,无论是写作还是阅读。
所以我想知道的是为什么索引操作符允许我访问值&#34;存储&#34;在给定索引处的向量x中,但不会改变其大小。
因为它没有被设计成以这种方式工作。可能设计师并不认为这种行为是可取的。
请注意std::vector::reserve
确实为矢量保留了内存,但实际上并没有改变它的大小。因此,在调用x.reserve(10)
之后,您的向量仍然具有0
的大小,尽管已经分配了10个元素的内部存储器。如果您现在要添加元素,则不能使用括号运算符,而是使用std::vector::push_back
。此功能会将矢量的大小增加1,然后追加您的项目。调用reserve
的优点是,多次调用push_back
时,不得重新分配向量的内存。
std::vector<double> x;
x.reserve(3);
x.push_back(3);
x.push_back(1);
x.push_back(7);
我认为您希望的行为可以使用std::vector::resize
来实现。此函数将内存保留为reserve
,然后实际更改向量的大小。
std::vector<double> x;
x.resize(3);
x[0] = 3;
x[1] = 1;
x[2] = 7;
之前的coude相当于:
std::vector<double> x(3);
x[0] = 3;
x[1] = 1;
x[2] = 7;
这里的大小是构造函数参数。以这种方式创建vector
会在创建时执行调整大小操作。