给定一个唯一(std::uint64_t
类型)整数的向量,如果我将(std::uint64_t
类型)的向量强制转换为(std::int64_t
类型)的向量,则可以保证是独特吗?
像这样铸造
std::vector<std::uint64_t> unsignedVec;
std::vector<std::int64_t> signedVec( unsignedVec.begin(), unsignedVec.end() );
答案 0 :(得分:8)
是否可以保证唯一?
形式上是实现定义的,但是在任何明智的平台上,它应该是唯一的。
(特别是如果提供int64_t
has to be 2的补码。)
自C ++ 20起,它具有唯一性。
https://en.cppreference.com/w/cpp/language/implicit_conversion#Numeric_conversions
如果目标类型是带符号的,则如果源整数可以用目标类型表示,则值不会更改。 [否则结果是实现定义的(直到C ++ 20)] [目标类型的唯一值等于源值的模2 n 其中,n是用于表示目标类型的位数。 (自C ++ 20起)。
答案 1 :(得分:3)
使用{p>结束于signedVec
的值
std::vector<std::int64_t> signedVec( unsignedVec.begin(), unsignedVec.end() );
如果unsignedVec
中的对应值大于std::int64_t
可以表示的值,则将在C ++ 11中实现定义。否则,值将是相同的[conv.integral]/3:
如果目标类型是带符号的,则该值可以用目标类型(和位域宽度)表示;否则,该值是实现定义的。
注意:C ++ 11通过[headers]/4从C99继承了std::int64_t
的定义。 int64_t
在C99 [7.18.1.1] / 1中被指定为(强调我;感谢@Bob__指出了这一点):
typedef名称
intN_t
指定一个带符号的整数类型,其宽度为 N ,没有填充位,并且用两个补码表示。
和[7.18.1.1] / 3
这些类型是可选的。但是,如果实现提供的整数类型的宽度为8位,16位,32位或64位,没有填充位,并且(对于有符号类型)具有二进制补码表示,则它应定义相应的typedef名称。
因此,尽管在技术上仍是实现定义的,但是如果代码编译,则值将不太可能是唯一的(只有在定义std::int64_t
时,值才是唯一的,因为这是可选的)。由于int64_t
被指定为具有二进制补码表示形式,并且仅在实现可以支持的情况下定义该定义,因此转换以除预期方式之外的任何方式运行都将非常令人惊讶。我从未听说过编译器无法正常运行。此外,如answer by @HolyBlackCat中指出的那样,从C ++ 20 [conv.integral]/3开始,将需要所需的行为…
答案 2 :(得分:1)
使用给定的代码,存在两种可能的情况:
unsignedVec
的所有元素均小于或等于std::numeric_limits<int64_t>::max()
。在这种情况下,目标向量元素将与原始向量元素相同,并且所有属性都将保留。std::numeric_limits<int64_t>::max()
。在这种情况下,程序行为未在标准中定义,应由实施来决定,一切都会发生。