为什么'auto'不尊重一元减号运算符?
Why does 'auto' not respect the unary minus operator?
我对C++很陌生,但我发现auto
的这种行为很奇怪:
class A{};
int main() {
A a;
auto x = -(sizeof(a));
cout << x << endl;
return 0;
}
在这种情况下,变量x是unsigned
,尽管我在初始化变量时使用了一元减号运算符。为什么只考虑sizeof
(std::size_t
(的返回类型,而不考虑由于使用了运算符而存储的数字将为负数的事实?
我知道size_t
是一个无符号整数
我已经在GCC 8.1.0和C++17中尝试过了。
这里的实际问题是,一元减号运算符的使用,就像其他内置算术运算符一样,是积分提升的主题。因此,令人惊讶的是,将一元负应用于size_t
的结果仍然是size_t
,并且没有必要责怪auto
。
反例。在这种情况下,由于整体促销,x
的类型为int
,因此输出为-1
:
unsigned short a{1};
auto x{-a};
cout << x << endl;
表达式-(sizeof(a))
将一元-
运算符应用于无符号类型的值。一元运算符不会将无符号整数值转换为有符号整数值;它定义了哪个无符号值将是这样一个操作的结果,如下所示(参见cppreference.com上的一元算术运算符(:
内置的一元减号运算符计算其提升操作数。对于无符号a,-a的值为2^b-a、 其中b是提升之后的比特数。
因此,即使令人惊讶,auto
也能正常工作,因为将一元-
运算符应用于无符号值的结果仍然是无符号值。
-
的结果为无符号,sizeof
返回无符号值。
一元运算符的操作数应具有算术或无范围枚举类型,结果是其操作数的否定。对积分或枚举操作数执行积分提升。无符号量的负数是通过减去其2^n中的值,其中n是提升操作数中的位数。结果的类型是提升操作数的类型。
[expr.unary.op]
sizeof
和sizeof...
的结果是类型为std::size_t
[expr.sizeof]
为了避免实现定义的行为,在应用-
之前,必须转换为int
如果目标类型已签名,则如果可以以目的地类型表示;否则,值为实现定义。
[conv.integral]
class A{};
int main() {
A a;
auto x = -(int{sizeof(a)});
cout << x << endl;
return 0;
}
如果我们看看:https://en.cppreference.com/w/cpp/language/sizeof,结果是类型size_t
,即unsigned
。您需要显式地将其声明为signed int
以允许负值。
您可以编写允许负值的int
,而不是auto
。
- 一元*运算符的操作数是否期望一个 prvalue
- 一元"运算符"未在C++中定义
- C2675 一元运算符由错误的作用域引起
- 你能帮我了解重载一元运算符和二进制运算符之间的区别吗?
- 泛型lambda和一元+运算符
- 创建指针是否超过非数组指针的末尾,而不是从 C++17 中的一元运算符和未定义的行为派生?
- 为什么我不能定义一元运算符,然后在 MSVC 的模板类中声明具有相同名称的友元二进制运算符?
- 为什么一元运算符和不需要完整类型?
- 在函数调用之前,一元运算符会否定运算符
- 一元运算符关联是否有意义
- 如何重载一元/运算符
- 使一元运算符为二进制运算符
- 如何从函数模板类成员内的转换算法参数指向一元运算符函数
- 运算符重载:一元运算符重载函数返回在此代码中如何工作
- C++中一元运算符重载困难
- MTL4 将一元运算符(例如 abs())元素应用于dense_vector<double>
- C++中的一元运算符重载类型(新手)
- 在C++中,将任意在位运算符转换为一元运算符
- 为后缀重载一元运算符
- 一元 + 运算符在 int& 上