一元+
运算符是否仅包含与一元-
运算符对称,还是在C ++代码中找到了一些实际用途?
在这里搜索,我遇到了What is the purpose of the unary '+' operator in C?,但唯一有用的场景涉及预处理器宏。这些都是很好的,但它们似乎是一些不常见的情况,并涉及宏。是否存在涉及更常见的C ++代码的用例?
答案 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 plus的Kleene Plus生成一个解析器规则,允许它的参数(解析器规则)匹配一次或多次。
答案 3 :(得分:4)
一元+
运算符将左值变为右值:
struct A {
static const int value = 1;
};
// ...
int x = std::min(0, A::value);
哦,不!此代码不会链接,因为有人忘了定义(以及声明)A::value
。 std::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
与类似指针的对象混淆。