一元运算+
符只是为了与一元运算符对称而包含-
,还是在 C++ 代码中找到了一些实际用途?
在这里搜索,我遇到了C中一元'+'运算符的目的是什么?,但唯一有用的场景涉及预处理器宏。这些很高兴知道,但它们似乎是一些不太常见的情况,并且涉及宏。是否有涉及更常见 C++ 代码的用例?
一元运算+
符只是为了与一元运算符对称而包含-
,还是在 C++ 代码中找到了一些实际用途?
在这里搜索,我遇到了C中一元'+'运算符的目的是什么?,但唯一有用的场景涉及预处理器宏。这些很高兴知道,但它们似乎是一些不太常见的情况,并且涉及宏。是否有涉及更常见 C++ 代码的用例?
char ch = 'a';
std::cout << ch << '\n';
std::cout << +ch << '\n';
第一次插入将字符a
写入cout
. ch
第二次插入写入to的数值cout
。但这有点晦涩难懂。它依赖于编译器为+
运算符应用积分提升。
一元对称-
并非完全没用。它可以用于强调:
const int foo = -1;
const int bar = +1;
重载的一元+
可用于表示产生与其操作数相同的逻辑值的操作,同时执行一些非平凡的计算。(我已经看到 Ada 中的类型转换这样做了,它允许+
重载 unary ,但不允许转换。)我手头没有一个好的 C++ 示例,有人可能会争辩说它的风格很差。(话又说回来,我看到很多关于超载的咆哮<<
。)
至于为什么C++ 有它,可能很大程度上是为了与 C 保持一致,它在 1989 年的 ANSI 标准中添加了它。C基本原理只是说:
一元加号被 C89 委员会从几个实现中采用,以与一元减号对称。
如果您明确地避开类的任何数值语义,则任何运算符重载都不会“像 int 那样做”。在这种情况下,一元加号可能有任何意义,做的不仅仅是返回*this
突出的例子:Boost.Spirit 的一元加法用于嵌入式 EBNF 的Kleene Plus生成一个解析器规则,让它的参数(也是一个解析器规则)匹配一次或多次。
一元运算+
符将左值转换为右值:
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);
一元加号创建一个具有相同值的临时,并且引用绑定到临时,因此我们可以解决缺少的定义。
这不是您经常需要的东西,但它是一元加运算符的实际用途。
一元 + 应用积分促销。@PeteBecker 的回答显示了一种有用的方法。
另一方面,请注意,一个无作用域的枚举类型被提升为一个整数类型,它可以表示enum
. 所以在 C++03 中,即使没有 C++11 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 );
}
有点晚了,但这是我偶然发现的一个非常扭曲的用法。显然,在+
围绕遇到空预处理器令牌的可能性设计安全措施时,操作员可能很有用(如果可能不是严格必要的话)。有关更深入的讨论,请参阅此帖子。
这很实用,但绝不是令人愉快的。
除其他外,+
将 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;},
};
由于算术变量 operator+ 会生成一个新值,因此我通常使用它来生成类引用(代理)类型的值副本。
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
可能会与类似指针的对象混淆。
因为对于算术变量 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
可能会与类似指针的对象混淆。