一元加运算符有什么作用?

时间:2009-04-07 20:44:44

标签: c# c++ c unary-operator

一元加运算符有什么作用?我找到了几个定义(herehere),但我仍然不知道它将用于什么。它似乎没有做任何事情,但有理由,对吗?

15 个答案:

答案 0 :(得分:102)

实际上,一元加做某事 - 即使在C语言中。它在操作数上执行 usual arithmetic conversions 并返回一个新值,该值可以是宽度更大的整数。如果原始值是宽度小于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是一个int”。

因此,在此示例中,一元加上使用不同类型的签名创建了一个新值。

答案 1 :(得分:53)

如果你觉得有必要的话就会超载;对于所有预定义类型,它基本上是一个无操作。

无操作一元算术运算符的实际用途非常有限,并且倾向于与在算术表达式中使用值的后果相关,而不是与运算符本身相关。例如,它可以用于强制从较小的整数类型扩展到int,或者确保表达式的结果被视为右值,因此与非const引用参数不兼容。但是,我提出,这些用途更适合编码高尔夫而不是可读性。 : - )

答案 2 :(得分:33)

来自K&amp; R第二版:

  

一元+是ANSI标准的新功能。它被添加为与一元对称的对称 - 。

答案 3 :(得分:31)

我看到它用于清晰,强调正值与负值不同:

shift(+1);
shift(-1);

但这是一个非常弱的用途。答案肯定是超载。

答案 4 :(得分:24)

内置的一元+做的一件事就是将左值变成右值。例如,你可以这样做

int x;
&x;

但你不能这样做

&+x;

:)

P.S。 “超载”绝对不是正确的答案。一元+继承自C,并且C中没有用户级运算符重载。

答案 5 :(得分:14)

一元+完成的主要内容是对小于int的数据类型的int类型提升。如果您尝试使用std::cout作为数字数据打印字符数据,这可能非常有用。

char x = 5;
std::cout << +x << "\n";

非常不同
char x=5;
std::cout << x << "\n";

它也可用于重载,但实际上你的重载应该几乎是NOP。

答案 6 :(得分:10)

如果您需要打印原始字节的数值(例如,存储为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

这只是一个简单的例子。我确信还有一些时候,一元+可以帮助处理你的字节更像数字而不是文字。

答案 7 :(得分:4)

历史花絮。 C99标准化委员会还认为,一元加的现有用法相当罕见,正如他们考虑重复使用它来实现该语言的另一个特征:抑制浮点常数表达式的翻译时评估。请参阅C基本原理F.7.4节中的以下引用:

  

该规范的早期版本允许转换时间常数算术,但是   授权一元+运算符,当应用于操作数时,禁止转换时间   评估常数表达式。

最后,语义被颠倒了,在大多数情况下执行运行时评估(至少达到“似乎”规则),并且能够通过使用静态初始化程序来强制执行翻译时评估。请注意,主要区别在于浮点异常的出现,以及其他存在的浮点舍入或精度设置。

答案 8 :(得分:3)

不多。允许operator+()重载的一般说法是,对于重载operator-()肯定存在真正的世界用途,如果你是的话,那么非常很奇怪(或不对称)允许重载operator-()而不是operator+()

我相信我第一次从Stroustrop那里读到了这个论点,但是我没有权利对我进行验证。我可能错了。

答案 9 :(得分:3)

一元加上出现在C中,它完全没有做任何事情(很像auto关键字)。为了不拥有它,Stroustrup将不得不引入与C的无偿不兼容。

一旦它在C ++中,很自然地允许一个重载函数,就像一元减号一样,而Stroustrup可能因为那个原因而引入它,如果它还没有。

所以,它没有任何意义。它可以用作一种装饰,使事物看起来更加对称,例如使用+1.5与-1.5相反。在C ++中,它可以被重载,但如果operator+()做任何事情,它会让人感到困惑。记住标准规则:当重载算术运算符时,请执行int s之类的操作。

如果你正在寻找它存在的原因,那就找一些关于C的早期历史的东西。我怀疑没有充分的理由,因为C并没有真正的设计。考虑无用的auto关键字(可能与static形成对比,现在在C ++ 0x中被回收),以及entry关键字,它从未做过任何事情(后来在C90中被省略) 。有一条着名的电子邮件,其中Ritchie或Kernighan说,当他们意识到运算符优先级有问题时,已经有三个安装了数千行代码而他们不想破解。

答案 10 :(得分:2)

我不能引用任何来源,但我已经明白它是用于显式类型提升,这意味着无损类型转换。这使它位于转换层次结构的顶部,

  • 推广: new_type operator+(old_type)
  • 转化: new_type(old_type)
  • 演员: operator(new_type)(old_type)
  • 强制: new_type operator=(old_type)

当然,这是我对15年前我读过的一本微软(非常旧的)c / c ++手册中的一个注释的解释,所以请大家用它。

答案 11 :(得分:1)

#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与一元+具有相同的优先级。

答案 12 :(得分:0)

我想你可以用它来做一个积极的数字。只需将一元+运算符重载为abs。除非你真的想混淆你的代码,否则不值得让你的开发人员感到困惑。然后它很好用。

答案 13 :(得分:0)

只是用来说服哪些数字为正数

例如;

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})

答案 14 :(得分:-1)

编辑完全重写,因为我在原来的回答中感到很沮丧。

这应该允许您将类型的显式声明作为正值处理(我认为主要是非数学运算)。似乎否定会更有用,但我想这里有一个例子,它可能会有所作为:

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; }
    }
}