在C++中,一元减号运算符如何处理布尔值

How does the unary minus operator work on booleans in C++?

本文关键字:布尔值 运算符 何处理 处理 一元 C++      更新时间:2023-10-16

我目前正在将一些OpenCV代码从C++转换为Java。我不能使用JavaCV,因为我们需要本地Java的转换,而不是JNA。在代码的某一点上,我得到了以下任务:

dst[x] = (uchar)(-(kHit >= kForeground));

其中dstuchar*kHitkForegroundint s。

我一直找不到关于这是如何工作的任何信息,Java也不会将其识别为一个操作。在代码的另一个点上对这两个变量有一个操作,它存储两个值中的一个:255或0。

有问题的代码来自opencv/video/src/bgfg_gaussmix.cpp

在C++中,布尔表达式会产生两个值之一—01。将一元减去-的值应用于结果时,将得到0-1。当您将-1重新解释为uchar时,您将得到255

您可以使用条件将此表达式转换为Java

dst[x] = (kHit >= kForeground) ? 255 : 0;

由于分支的原因,它不会像原来那样快。然而,对于它的速度,您几乎无能为力,因为Java缺乏将布尔值重新解释为数字的能力。

kHit >= kForeground返回truefalse,在C++中,这意味着10。前面的减号将其转换为-10。对uchar的强制转换((uchar))对于0返回0,并且对于负-1返回到255

在Konrad的评论之后,我也怀疑这一点是否明确它定义得很好,但就可读性而言,它仍然是一段糟糕的代码。:)

它的基本功能如下:

kHit >= kForeground

是布尔类型的表达式

-(kHit >= kForeground)

将该布尔转换为int(基于true==1false==0)并求反,从而得到true==-1false==0

然后将其转换为uchar,从而产生-1==2550==0

必须注意的是,尽管看起来像是在使用数字的底层实现细节,但所有这些转换都是由C++和C标准保证的,因为负无符号数字被指定为根据二进制补码表现。

但是,如果Java不支持这一点,您总是可以用一个条件赋值来代替它:

dst[x] = (kHit>=kForeground) ? 255 : 0;

表达式(kHit >= kForeground)生成一个值为truefalse的布尔值。当应用一元-时,bool被提升为int,并且转换为true1false0。升级后,符号被更改为-10,然后通过外部铸造转换为uchar

注意,信息的重要部分是一元operator-不应用于布尔值,而是将布尔值转换为int,然后应用它。这可以用一点模板魔法来测试:

template <typename T, typename U>
struct same_type {
    static const bool value = false;
};
template <typename T>
struct same_type<T,T> {
    static const bool value = true;
};
template <typename T>
void f( T value ) {
    std::cout << "Is int? " << std::boolalpha << same_type<T, int>::value << "n";
    std::cout << "Is bool? " << same_type<T, bool>::value << "n";
}
int main() {
    f(-true);
}

f模板通过使用上面的same_type模板来测试针对intbool传递的参数的类型(琐碎到可以理解)。如果我们用-true作为参数类型来调用f模板,则推导会将T设置为表达式-true的类型。如果您运行该程序,您将看到它打印Is int? truenIs bool? false