从不同类型容器的迭代器初始化向量
Posted
技术标签:
【中文标题】从不同类型容器的迭代器初始化向量【英文标题】:Initializing a vector from iterators of a container of a different type 【发布时间】:2017-06-28 12:09:18 【问题描述】:给出以下代码:
#include <iterator>
#include <vector>
int main()
char arr[3] = 1,2,3 ;
std::vector<char> vec = 1,2,3 ;
std::vector<int> vec_one(std::begin(arr), std::end(arr));
std::vector<int> vec_two(vec.begin(), vec.end());
vec_one
和 vec_two
的初始化是未定义的,实现是根据普通类型转换规则定义还是定义?
如果交换了char
和int
类型怎么办?
【问题讨论】:
我不明白这个问题的否决票。它清楚地解释了问题,提供了minimal reproducible example,并且与大多数带有c++ 标签的问题相比,它非常通用和抽象。 @IInspectable:我完全同意。目前的答案(包括我的)可能会更全面。 我没有对这个投票,因为虽然我喜欢清晰,但没有研究成果的证明。但我确实觉得投反对票是不公平的。 @rex:再一次,到达从迭代器构造容器的地步,实现minimal reproducible example(是最小的和完整的),并使用术语“未定义”、“实现定义”和“(良好)定义”需要(并证明)更多研究努力,而不是这里的其他问题。 我想我们可以达到这样的地步,即通过引用 C++ 标准可以回答的每个问题都可以因为没有显示研究工作而被关闭。 【参考方案1】:它们都很好,在将char
转换为int
(所以不用担心)和int
转换为char
时适用相同的规则,这将再次受到正常规则的约束:如果char
是signed
(否则行为是未定义),则int
必须足够小以适合char
,如果char
则定义明确的环绕行为是unsigned
。
【讨论】:
所以副本埋在向量初始化/构造函数中这一事实没有区别?我认为这很明显,但这是将这个问题与通用 intchar 转换问题区分开来的唯一因素。 没有。我会标记“语言律师”,希望有人发布一个充满标准参考的答案。 @rex 这就是问题的原因,这是您 99% 确定但最好是 100% 的情况之一。 你也可以这样用列表初始化向量,【参考方案2】:除了一种情况外,这都是定义良好的代码。 int
必须至少与char
具有相同的大小,并且至少能够存储 16 位二进制补码整数可以存储的内容。因此,当sizeof(char) < sizeof(int)
行为被明确定义为您int
可以存储每个值char
可以。如果sizeof(char) ==
sizeof(int)and
charis an alias to
unsigned charthen you could overflow the
int`这是未定义的行为。
相反的情况也有未定义的行为。如果char
是signed char
和sizeof(int) > sizeof(char)
的别名,那么您可以将int
溢出转换为char
,这是有符号整数溢出并且是未定义的行为。如果char
是unsigned char
的别名,尽管它永远不会是未定义的行为。
【讨论】:
第一句话并不完全正确。char
的签名是实现定义的。考虑一个未签名的char
,以及一个与char
具有相同范围的已签名int
。该转换无效(据我所知)。另外(据我所知),int
至少有 16 位宽,从 C 标准合并而来,所以这个问题基本上没有实际意义。
整数截断不是未定义的行为。截断的结果确实非常明确,这些天 UB 术语被过度使用了。
@MichaëlRoy:嗯,没错。尽管如此,我指的是短语“可以毫无问题地转换[...]”。 (潜在的)截断,但是,是一个问题,您需要注意(如果允许 int
与 char
大小相同)。
@IInspectable 你是对的。我错过了那个边缘案例。我已经更新了答案,希望现在它涵盖了所有内容。以上是关于从不同类型容器的迭代器初始化向量的主要内容,如果未能解决你的问题,请参考以下文章