从不同类型容器的迭代器初始化向量

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_onevec_two 的初始化是未定义的,实现是根据普通类型转换规则定义还是定义? 如果交换了charint 类型怎么办?

【问题讨论】:

我不明白这个问题的否决票。它清楚地解释了问题,提供了minimal reproducible example,并且与大多数带有c++ 标签的问题相比,它非常通用和抽象。 @IInspectable:我完全同意。目前的答案(包括我的)可能会更全面。 我没有对这个投票,因为虽然我喜欢清晰,但没有研究成果的证明。但我确实觉得投反对票是不公平的。 @rex:再一次,到达从迭代器构造容器的地步,实现minimal reproducible example(最小的完整的),并使用术语“未定义”“实现定义”“(良好)定义”需要(并证明)更多研究努力,而不是这里的其他问题。 我想我们可以达到这样的地步,即通过引用 C++ 标准可以回答的每个问题都可以因为没有显示研究工作而被关闭。 【参考方案1】:

它们都很好,在将char 转换为int(所以不用担心)和int 转换为char 时适用相同的规则,这将再次受到正常规则的约束:如果charsigned(否则行为是未定义),则int 必须足够小以适合char,如果char 则定义明确的环绕行为是unsigned

【讨论】:

所以副本埋在向量初始化/构造函数中这一事实没有区别?我认为这很明显,但这是将这个问题与通用 intchar 转换问题区分开来的唯一因素。 没有。我会标记“语言律师”,希望有人发布一个充满标准参考的答案。 @rex 这就是问题的原因,这是您 99% 确定但最好是 100% 的情况之一。 你也可以这样用列表初始化向量,【参考方案2】:

除了一种情况外,这都是定义良好的代码。 int 必须至少与char 具有相同的大小,并且至少能够存储 16 位二进制补码整数可以存储的内容。因此,当sizeof(char) &lt; sizeof(int) 行为被明确定义为您int 可以存储每个值char 可以。如果sizeof(char) ==sizeof(int)andcharis an alias tounsigned charthen you could overflow theint`这是未定义的行为。

相反的情况也有未定义的行为。如果charsigned charsizeof(int) &gt; sizeof(char) 的别名,那么您可以将int 溢出转换为char,这是有符号整数溢出并且是未定义的行为。如果charunsigned char 的别名,尽管它永远不会是未定义的行为。

【讨论】:

第一句话并不完全正确。 char 的签名是实现定义的。考虑一个未签名的char,以及一个与char 具有相同范围的已签名int。该转换无效(据我所知)。另外(据我所知),int 至少有 16 位宽,从 C 标准合并而来,所以这个问题基本上没有实际意义。 整数截断不是未定义的行为。截断的结果确实非常明确,这些天 UB 术语被过度使用了。 @MichaëlRoy:嗯,没错。尽管如此,我指的是短语“可以毫无问题地转换[...]”。 (潜在的)截断,但是,一个问题,您需要注意(如果允许 intchar 大小相同)。 @IInspectable 你是对的。我错过了那个边缘案例。我已经更新了答案,希望现在它涵盖了所有内容。

以上是关于从不同类型容器的迭代器初始化向量的主要内容,如果未能解决你的问题,请参考以下文章

C++迭代器的使用和操作总结

练笔-字符串,向量和数组6

指向特定类型的 STL 容器样式和迭代器 (C++)

java迭代器demo

C++ 字符串向量和数组的一些术语

C++ 字符串向量和数组的一些术语