vector元素的初始化顺序是否有标准保证?
Is the initialization order of the vector elements guaranteed by the standard?
要从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);
//...
}
问题:
- vector元素的初始化顺序是否由标准(0,1,2,n-1...)保证?
- (如果上一个问题的答案是真的)第二个变体真的有两倍的效果吗?
我对符合 C++11(及更新版本)标准的行为感兴趣
关于你的第一个问题,C++20
(但这也可以追溯到 C++11
)处理 vector
序列容器的部分使得 no 承诺在向量本身中构造元素的顺序,只是将元素设置为某个特定值:
Effects: Constructs a vector
with n
default-inserted elements.
关于那个(非常简短的)部分的顺序根本没有任何内容(a)。
但是你的方法有一个更大的问题,具体来说,我不认为你真的想在你遇到的每一种情况下都去cin
默认构造点变量。
例如,在某些情况下,您需要一个默认构造的临时变量,如果您的程序突然停止接受用户输入,尤其是在没有提示用户的情况下,它将被视为挂起:- )
这让你的第二个问题没有实际意义,但是,假设你担心初始化向量元素然后用输入循环更改它们的效率低下,我不会。没有构造函数的结构(即只有几个 int
变量)不需要 初始化它们(b),所以他们的向量可以做分配并停在那里。
(a) 某些顺序 是 标准中保证的,例如 class 中不同成员的顺序,或数组中元素的顺序。但是,矢量的元素不是这些东西。
(b) 这包含在 C++20 10.9 Iniitialisation [class.init]
:
When no initializer is specified for an object of (possibly cv-qualified) class type (or array thereof), or the initializer has the form ()
, the object is initialized as specified in 9.3
.
和C++20 9.3 Initializers [dcl.init]
:
To default-initialize an object of type T
means:
- If
T
is a (possibly cv-qualified) class type, constructors are considered. The applicable constructors are enumerated, and the best one for the initializer ()
is chosen through overload resolution. The constructor thus selected is called, with an empty argument list, to initialize the object.
- If
T
is an array type, each element is default-initialized.
- Otherwise, no initialization is performed.
这是针对没有显式定义或继承构造函数的类型的第一个要点。在那种情况下,它使用隐式定义的构造函数,它等效于没有主体和初始化列表的用户定义的构造函数。
不保证元素按照其索引的顺序进行初始化。在 C++11 中,参见 [vector.cons]/3:
Effects: Constructs a vector
with n
value-initialized elements.
这没有说明顺序,因此无法假设。标准的更高版本中的措辞发生了变化,但似乎从未强加任何顺序。
要从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);
//...
}
问题:
- vector元素的初始化顺序是否由标准(0,1,2,n-1...)保证?
- (如果上一个问题的答案是真的)第二个变体真的有两倍的效果吗?
我对符合 C++11(及更新版本)标准的行为感兴趣
关于你的第一个问题,C++20
(但这也可以追溯到 C++11
)处理 vector
序列容器的部分使得 no 承诺在向量本身中构造元素的顺序,只是将元素设置为某个特定值:
Effects: Constructs a
vector
withn
default-inserted elements.
关于那个(非常简短的)部分的顺序根本没有任何内容(a)。
但是你的方法有一个更大的问题,具体来说,我不认为你真的想在你遇到的每一种情况下都去cin
默认构造点变量。
例如,在某些情况下,您需要一个默认构造的临时变量,如果您的程序突然停止接受用户输入,尤其是在没有提示用户的情况下,它将被视为挂起:- )
这让你的第二个问题没有实际意义,但是,假设你担心初始化向量元素然后用输入循环更改它们的效率低下,我不会。没有构造函数的结构(即只有几个 int
变量)不需要 初始化它们(b),所以他们的向量可以做分配并停在那里。
(a) 某些顺序 是 标准中保证的,例如 class 中不同成员的顺序,或数组中元素的顺序。但是,矢量的元素不是这些东西。
(b) 这包含在 C++20 10.9 Iniitialisation [class.init]
:
When no initializer is specified for an object of (possibly cv-qualified) class type (or array thereof), or the initializer has the form
()
, the object is initialized as specified in9.3
.
和C++20 9.3 Initializers [dcl.init]
:
To default-initialize an object of type
T
means:
- If
T
is a (possibly cv-qualified) class type, constructors are considered. The applicable constructors are enumerated, and the best one for the initializer()
is chosen through overload resolution. The constructor thus selected is called, with an empty argument list, to initialize the object.- If
T
is an array type, each element is default-initialized.- Otherwise, no initialization is performed.
这是针对没有显式定义或继承构造函数的类型的第一个要点。在那种情况下,它使用隐式定义的构造函数,它等效于没有主体和初始化列表的用户定义的构造函数。
不保证元素按照其索引的顺序进行初始化。在 C++11 中,参见 [vector.cons]/3:
Effects: Constructs a
vector
withn
value-initialized elements.
这没有说明顺序,因此无法假设。标准的更高版本中的措辞发生了变化,但似乎从未强加任何顺序。