标准是否保证了向量元素的初始化顺序?

11

我通常使用以下代码从std::cin中填充一个std::vector<struct_name>

struct point{
    int x, y;
};

int main()
{
   std::size_t n;
   std::cin>>n; 
   std::vector<point> vec(n);
    for (auto& p:vec) 
        std::cin>>p.x>>p.y;
   //...
}

但是今天我发现另一种使用默认构造函数的方式:

struct point{
int x, y;
   point(){
      std::cin>>x>>y;
   }
};

int main()
{
    std::size_t n;
    std::cin>>n; 
    std::vector<point> vec(n);
    //...
}

问题:

  1. 向量元素的初始化顺序是否由标准保证(0、1、2、n-1...)?
  2. (如果上一个问题的答案是正确的)真的第二种变体有效吗?

我对C++11(及更新版本)标准下的行为感兴趣


4
除了是否有保证订单的问题之外,使用构造函数来输入数据看起来对我来说很糟糕。构造函数应该尽可能“清晰简洁”。你的第一个解决方案看起来更好一些。 - TonyK
std::cin可能不是一个很好的例子,但我认为能否在那里重载函数的问题确实很有趣。 - benni
2个回答

13

不能保证元素按照它们的索引值初始化。在C++11中,请参见[vector.cons] / 3:

作用:构造一个具有n个值初始化元素的vector

这并没有说明顺序,因此不能假定任何顺序。标准的后续版本中措辞有所变化,但似乎从未强制规定任何顺序。


6
关于你的第一个问题,处理向量(vector)序列容器的 C++20(但这一点可以追溯到 C++11)部分并不保证元素在向量本身内部构建的顺序,只保证将元素设置为某些特定值:

效果: 使用默认插入的元素构造一个vector

在该 (非常简短的) 部分中没有任何关于那个顺序的说明。
但是,你的方法存在一个更大的问题,具体地说,我认为你在每个需要默认构造点变量的情况下都不希望去接收cin读取输入。
例如,有可能存在需要默认构造临时变量,如果程序突然停止接受用户输入,这就会导致程序卡死,特别是如果没有向用户提示 :-)。
这使得你的第二个问题无关紧要,但是假设你担心初始化向量元素的效率问题,然后再使用输入循环来修改它们,那么我不会担心。没有构造函数的结构(即仅有一对变量)不需要初始化((b)),因此它们所组成的向量可以只进行分配操作,而无需进一步初始化。
(a)标准中确实保证了某些顺序,例如类中不同成员的顺序或数组中元素的顺序。然而,向量的元素既不是类中的那些成员,也不是数组中的那些元素。
(b)这在 C++20 10.9 Iniitialisation [class.init] 中有所涉及:

当没有为 (可能带有cv限定符的) 类类型(或其中的数组) 的对象指定初始化程序时,或者初始化程序的形式为 () 时,将按照 9.3 中规定的方式初始化该对象。

以及 C++20 9.3 Initializers [dcl.init] 中提到的:

对于类型 T 的默认初始化,意思是:

  • 如果 T 是一个 (可能带有cv限定符的) 类类型,则将考虑其构造函数。应用的构造函数被枚举,并为初始化器 () 选择最佳的构造函数,通过重载解析进行选择。因此,选择的构造函数被调用,具有空参数列表,以初始化对象。
  • 如果 T 是一个数组类型,则每个元素都进行默认初始化。
  • 否则,不执行任何初始化操作。
就是针对没有显式定义或继承构造函数的类型,会应用第一个子弹点中的规则。在这种情况下,它使用等效于没有该列表和没有初始值的用户自定义构造函数的隐式定义构造函数。

@paxdiablo 谢谢!但我已经意识到这个问题了。我只是在解决一个小的教学任务。我认为第二个选项会提高效率。但如果不能保证顺序,那么我应该选择第一个选项。 - PavelDev
@PavelDev:请查看我对您潜在效率提升的更新。即使顺序是有保证的,我认为您也不会看到太大的改进,因为创建一个默认初始化成员向量基本上只是内存分配 - 不会有元素在向量中进行双重设置。 - paxdiablo
1
@paxdiablo -- 即使 point 的默认构造函数将两个成员变量都初始化为某些值,但之后读入实际值所需的时间将比这短得多。I/O 操作非常慢;与此相比,任何内部操作都是即时的。 - Pete Becker

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接