一元+算子有实际用途吗?

时间:2013-01-16 19:01:16

标签: c++ operators unary-operator

一元+运算符是否仅包含与一元-运算符对称,还是在C ++代码中找到了一些实际用途?

在这里搜索,我遇到了What is the purpose of the unary '+' operator in C?,但唯一有用的场景涉及预处理器宏。这些都是很好的,但它们似乎是一些不常见的情况,并涉及宏。是否存在涉及更常见的C ++代码的用例?

9 个答案:

答案 0 :(得分:31)

char ch = 'a';
std::cout << ch << '\n';
std::cout << +ch << '\n';

第一次插入会将字符a写入cout。第二次插入将ch的数值写入cout。但这有点模糊;它依赖于编译器对+运算符应用整数提升。

答案 1 :(得分:21)

与一元-的对称并非完全无用;它可以用于强调:

const int foo = -1;
const int bar = +1;

重载一元+可用于表示产生与其操作数相同的逻辑值的操作,同时执行一些非平凡的计算。 (我已经看到这在Ada中的类型转换中完成了,它允许一元+但不允许转换。)我没有一个好的C ++示例可以提供,并且有人可能会认为它会是穷人的风格。 (然后,我看到很多关于重载<<的咆哮。)

至于为什么 C ++拥有它,它可能主要是为了与C的一致性,它增加了1989 ANSI标准。 C Rationale只是说:

  

一致加上C89委员会从几个人那里获得通过   实现,对称与一元减号。

答案 2 :(得分:10)

如果你明确地忽略了类的任何数值语义,那么任何运算符重载都是明确的,而不是“按照这样做”。在这种情况下,一元加号可能有任何意义,不仅仅是返回*this

突出示例:嵌入式EBNF Boost.Spirit's unary plusKleene Plus生成一个解析器规则,允许它的参数(解析器规则)匹配一次或多次。

答案 3 :(得分:4)

一元+运算符将左值变为右值:

struct A {
  static const int value = 1;
};

// ...

int x = std::min(0, A::value);

哦,不!此代码不会链接,因为有人忘了定义(以及声明)A::valuestd::min通过引用获取其参数,因此A::value必须有一个地址,以便引用可以绑定到它(从技术上讲,一个定义规则说它必须在程序中只定义一次。)

没关系,一元加上救援:

int x = std::min(0, +A::value);

一元加号创建一个具有相同值的临时值,并且引用绑定到临时值,因此我们可以解决缺少的定义。

这不是您经常需要的,但它是一元加运算符的实际用途。

答案 4 :(得分:1)

一元+适用整体促销。 @ PeteBecker的答案显示了一种有用的方法。

另一方面,请注意,未范围的枚举类型会被提升为整数类型,该整数类型可以表示enum中的所有值。所以在C ++ 03中,即使没有C ++ 11&#39; std::underlying_type<T>,你也可以这样做:

enum MyBitMask {
    Flag1 = 0x1,
    Flag2 = 0x2,
    Flag3 = 0x4,
    Flag4 = 0x8000000
};

inline MyBitMask operator&(MyBitMask x, MyBitMask y) {
    return static_cast<MyBitMask>( +x & +y );
}

inline MyBitMask operator|(MyBitMask x, MyBitMask y) {
    return static_cast<MyBitMask>( +x | +y );
}

答案 5 :(得分:1)

有点晚了,但这是一个非常扭曲的用途我偶然发现了。显然,在设计围绕遇到空预处理器令牌的可能性的保护措施时,+运算符可能很有用(如果可能不是绝对必要的话)。有关更深入的讨论,请参阅this post

这很实用,但绝不令人愉快。

答案 6 :(得分:0)

因为算术变量,operator +会生成一个新值。 我用它来生成引用型(代理)类型的值副本。

template<class T> class ref_of{
   T* impl_; // or a more complicated implementation
public:
   T operator+() const{return *impl_;}
   operator T&()&{return *impl_;}
}

另一种选择是使用operator*,但是可以将ref_of与类似指针的对象混淆。

答案 7 :(得分:0)

除其他事项外,+将lambda转换为函数指针。通常情况下,转换会自动发生,但有时不会自动发生。

例如,它不会编译:

std::array arr{
    [](int x){return x*x;},
    [](int x){return x*x*x;},
};

您可以通过将函数指针类型指定为std::array模板参数来使它起作用,或者,您可以这样做:

std::array arr{
    +[](int x){return x*x;},
    +[](int x){return x*x*x;},
};

答案 8 :(得分:0)

由于算术变量operator +会生成一个 new 值, 我通常使用它来生成引用类型(代理)类型的值副本。

template<class T> class ref_of{
   T* impl_; // or a more complicated implementation
public:
   T operator+() const{return *impl_;} 
   operator T&()&{return *impl_;}
}
...
ref_of<T> r = t;
auto s = +r; // this forces a copy

另一种选择是使用operator*,但是可以将ref_of与类似指针的对象混淆。