为什么在C 中使用索引运算符被认为是不好的样式



我正在研究使用向量的程序。所以我做的第一件事是声明我的矢量。

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]如果不存在,则创建值,则效率将有两次命中。首先,索引操作的呼叫者应确保索引不超出向量的当前大小。其次,即使您要为其分配一个新值,也需要默认构建新元素。

具有reserveresize的原因相似。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这样的方式在创建上执行调整大小操作。

最新更新