一元加号运算符有什么作用?我找到了几个定义(here和here),但我仍然不知道它的用途。看起来它什么也没做,但这是有原因的,对吧?
15 回答
实际上,一元加号确实做了一些事情——即使在 C 中也是如此。它对操作数执行通常的算术转换并返回一个新值,该值可以是更大宽度的整数。如果原始值是一个宽度小于 的无符号整数int
,它也会被更改为一个signed
值。
通常这不是那么重要,但它会产生影响,因此使用一元加号作为一种表示整数为正的“注释”并不是一个好主意。考虑以下 C++ 程序:
void foo(unsigned short x)
{
std::cout << "x is an unsigned short" << std::endl;
}
void foo(int x)
{
std::cout << "x is an int" << std::endl;
}
int main()
{
unsigned short x = 5;
foo(+x);
}
这将显示“x is an int”。
所以在这个例子中,一元加号创建了一个具有不同类型和符号的新值。
如果您觉得需要,它就会超载;对于所有预定义类型,它本质上是无操作的。
无操作一元算术运算符的实际用途非常有限,并且往往与在算术表达式中使用值的结果有关,而不是与运算符本身有关。例如,它可用于强制从较小的整数类型扩展为int
,或确保表达式的结果被视为右值,因此与非const
引用参数不兼容。然而,我认为这些用途比可读性更适合编码高尔夫。:-)
来自 K&R 第二版:
一元 + 是 ANSI 标准的新符号。添加它是为了与一元 - 对称。
我已经看到它用于清晰,强调正值与负值不同:
shift(+1);
shift(-1);
但这是一个相当弱的用途。答案肯定是超载。
内置一元+
所做的一件事是将左值转换为右值。例如,您可以这样做
int x;
&x;
但你不能这样做
&+x;
:)
PS“重载”绝对不是正确的答案。一元+
是从 C 继承的,C 中没有用户级运算符重载。
一元 + 完成的主要事情是将小于 int 数据类型的类型提升为 int。如果您尝试使用std::cout
数字数据打印 char 数据,这将非常有用。
char x = 5;
std::cout << +x << "\n";
与
char x=5;
std::cout << x << "\n";
它也可用于重载,但实际上您的重载应该几乎是 NOP。
如果您出于调试或任何原因需要打印原始字节的数值(例如,存储为 char 的小数),一元 + 可以简化打印代码。考虑
char c = 42;
cout << c << endl; // prints "*\n", not what you want in this case
cout << (int)c << endl; // prints "42\n", ok
cout << +c << endl; // prints "42\n", much easier to type
这只是一个简单的例子。我确信在其他时候一元 + 可以帮助您将字节更像数字而不是文本。
一个历史花絮。C99 标准化委员会还认为一元加法的现有用途相当少见,他们考虑重用它以实现语言中的另一个特性就证明了这一点:抑制浮点常量表达式的翻译时求值。请参阅 C 基本原理,第 F.7.4 节中的以下引用:
该规范的早期版本允许翻译时常量算术,但授权一元 + 运算符,当应用于操作数时,禁止常量表达式的翻译时求值。
最后,语义被颠倒了,在大多数上下文中强制执行运行时评估(至少达到“好像”规则),并且能够通过使用静态初始化器来强制执行翻译时评估。请注意,主要区别在于浮点异常的发生以及其他浮点舍入或精度设置(如果存在)。
不多。允许重载的一般论点operator+()
是,重载肯定有现实世界的用途,如果你允许重载但不允许重载operator-()
,那将是非常奇怪的(或不对称的) 。operator-()
operator+()
我相信我首先从 Stroustrop 那里读到了这个论点,但我没有我的书来验证它。我可能错了。
一元加号出现在 C 中,它完全没有做任何事情(很像auto
关键字)。为了不拥有它,Stroustrup 将不得不引入与 C 的无缘无故的不兼容。
一旦它出现在 C++ 中,就很自然地允许重载函数,就像一元减法一样,如果它还没有的话,Stroustrup 可能会因为这个原因引入它。
所以,没什么意思。它可以用作一种装饰,使事物看起来更对称,例如使用 +1.5 与 -1.5 相反。在 C++ 中,它可以被重载,但如果operator+()
做任何事情会令人困惑。记住标准规则:当重载算术运算符时,像int
s 那样做。
如果您正在寻找它存在的原因,请查找有关 C 早期历史的一些信息。我怀疑没有充分的理由,因为 C 并不是真正设计的。考虑无用auto
关键字(可能与static
,现在在 C++0x 中被回收)和entry
关键字,它从来没有做任何事情(后来在 C90 中被省略)。有一封著名的电子邮件,Ritchie 或 Kernighan 说,当他们意识到运算符优先级存在问题时,已经有 3 个安装有数千行代码,他们不想破坏。
我不能为此引用任何来源,但我已经明白它是用于显式类型提升,这意味着无损类型转换。这使它位于转换层次结构的顶部,
- 晋升:
new_type operator+(old_type)
- 转换:
new_type(old_type)
- 投掷:
operator(new_type)(old_type)
- 强迫:
new_type operator=(old_type)
当然,这是我对大约 15 年前阅读的一本微软(非常老的)c/c++ 手册中的注释的解释,因此请谨慎对待。
#include <stdio.h>
int main()
{
unsigned short x = 5;
printf ("%d\n",sizeof(+x));
printf ("%d\n",sizeof(x));
return 0;
}
如上例所示,一元 + 确实改变了类型,大小分别为 4 和 2。奇怪的是表达式 +x 确实是在 sizeof 中计算的,我认为这不应该。也许是因为 sizeof 与一元 + 具有相同的优先级。
编辑完全重写,因为我在我原来的答案中很糟糕。
这应该允许您将类型的显式声明处理为正值(我认为主要是非数学运算)。似乎否定会更有用,但我想这是一个可能会产生影响的例子:
public struct Acceleration
{
private readonly decimal rate;
private readonly Vector vector;
public Acceleration(decimal rate, Vector vector)
{
this.vector = vector;
this.rate = rate;
}
public static Acceleration operator +(Acceleration other)
{
if (other.Vector.Z >= 0)
{
return other;
}
return new Acceleration(other.Rate, new Vector(other.vector.X, other.Vector.Y, -other.vector.Z));
}
public static Acceleration operator -(Acceleration other)
{
if (other.Vector.Z <= 0)
{
return other;
}
return new Acceleration(other.Rate, new Vector(other.vector.X, other.Vector.Y, -other.vector.Z));
}
public decimal Rate
{
get { return rate; }
}
public Vector Vector
{
get { return vector; }
}
}
我想您可以使用它来始终使数字为正数。只需将一元 + 运算符重载为 abs。真的不值得混淆你的开发者伙伴,除非你真的只是想混淆你的代码。然后它会很好地工作。
只是用来说服哪些数字是正数的
例如;
int a=10;
System.out.println(+x);// prints 10(that means,that number 10 multiply by +1,{10*+1})
//if we use unary minus
int a=10;
System.out.println(-x);//prints -10(that means,that number 10 multiply by +1,{10*-1})