我正在研究使用向量的程序。所以我做的第一件事是声明我的矢量。
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
。
所以我想知道的是为什么索引运算符让我在给定索引中访问向量x
中的"存储"值,但不会改变其大小。另外,为什么这种不良习惯?
当您进行x.reserve(10)
时,您只将 apcation 设置为十个元素,但是 size 仍然为零。
这意味着然后您在循环中使用索引操作员,您将脱离界限(因为大小为零),并且您将具有不确定的行为。
如果要设置大小,请使用resize
或在构造向量时简单地告诉它:
std::vector<double> x(10);
至于矢量的容量,当您设置它时(使用例如reserve
),则分配(在您的情况下)十个元素所需的内存。这意味着当您执行push_back
时,矢量数据将没有重新分配。
如果您不更改容量或添加元素以外的容量,则每个push_back
可能会导致向量数据的重新分配。
听起来您在问为什么事情是这样的。大部分都取决于效率。
如果x[i]
如果不存在,则创建值,则效率将有两次命中。首先,索引操作的呼叫者应确保索引不超出向量的当前大小。其次,即使您要为其分配一个新值,也需要默认构建新元素。
具有reserve
和resize
的原因相似。resize
需要每个元素的默认结构。对于像vector<double>
这样的东西似乎没什么大不了的,但是对于vector<ComplicatedClass>
来说,这确实是一件大事。使用reserve
是一种优化,完全可选,可让您预测向量的最终大小并在其生长时预防重新分离。
push_back
避免了元素的默认结构,由于内容已知,因此可以使用移动或复制构造函数。
这都不是错误的样式,使用适合您情况的任何样式。
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 中使用索引运算符?
通常不是。如果您尝试访问的索引上没有元素,这是错误的(不仅是错误的样式)。
我应该只输入
std::vector<double> x(10)
?
绝对是!
如@Some程序员花花公子的答案std::vector::reserve()
仅影响分配策略,但不影响向量的大小。
std::vector<double> x(10);
实际上等于
std::vector<double> x;
x.resize(10);
std::vector
的支架操作员可让您在向量的索引i
处访问项目。如果不存在一个项目i
,则无法访问它,否则既不用于写作也无法阅读。
所以我想知道的是为什么索引运算符让我在给定索引中访问向量X中的"存储"值,但不会更改其大小。
因为它不是为此设计的。设计师可能不认为这种行为是可取的。
另外,请注意,std::vector::reserve
确实为矢量保留内存,但实际上并没有改变其大小。因此,调用x.reserve(10)
后,您的向量仍然具有0
的大小,尽管已分配了10个元素的内存。如果您现在想添加一个元素,则不得使用括号运算符,而是使用std::vector::push_back
。此功能将使向量的大小增加一个,然后附加您的项目。调用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;
以前的代码等效于:
std::vector<double> x(3);
x[0] = 3;
x[1] = 1;
x[2] = 7;
这里的大小是构造函数参数。创建vector
这样的方式在创建上执行调整大小操作。