Visual Studio 2019/C++ 错误?

Visual Studio 2019/C++ bug?

我在 Visual Studio 2019 16.11.8 中使用本机 C++。 我不明白这一点:false 关键字可以用作 NULL(或 nullptr)吗?测试代码下方:

bool test(bool* pb)
{
    if (NULL != pb)
        return *pb;
    else
        return false;
}

void main()
{
    test(false); // compiles (not what I was expecting)
    test(true); // won't compile: error C2664: 'test' : cannot convert parameter 1 from 'bool' to 'bool *'
}

我试过在线编译工具,他们不接受

test(false);

行,在我看来正常行为应该是什么。

此外,此行为可能会导致重载方法出现问题。即,您有一个 test(bool* pb) 方法和一个带有指针的重载版本:test(int* pv)

bool test(bool* pb)
{
    if (NULL != pb)
        return *pb;
    else
        return false;
}

bool test(int* pb)
{
    if (NULL != pb)
        return true;
    else
        return false;
}

void main()
{
    test(false); // won't compile anymore: error C2668: 'test' : ambiguous call to overloaded function
    test(true); // won't compile: error C2664: 'test' : cannot convert parameter 1 from 'bool' to 'bool *'
}

顺便说一句,我也在使用 VS2012,它具有相同的行为和相同的测试代码。

这不是错误。 测试函数有类似的参数指针。假 == 0 == 空。你可以有一个 NULL 指针。 但是 true = 1。您不能将 1(bool 或 int)转换为指针。

改为:

bool test(int& pb)
{
    if (pb)
        return true;
    else
        return false;
}

pb != NULLpb != false都可以,但更好的是if(pb)

MSVC 将表达式 false 视为 空指针常量 .

空指针常量可以隐式转换为任何指针类型,从而产生空指针值。

根据标准,正确的行为是仅将值为 0 的整数文字视为空指针常量。虽然它有值 0,但 false 不是整数文字。

然而,此规则仅在 CWG issue 903 决议后生效。在此之前,每个值为 0 的整型常量表达式都是空指针常量。

MSVC 没有使用默认标志实现缺陷报告,仍然遵循这个旧规则,根据该规则,表达式 false 是一个空指针常量。

如果您给 MSVC 标志 /permissive- 使其表现得更符合标准并实施新规则。对于 /std:c++20 或更高版本,这也是默认设置,如果我没记错的话。

但是请注意,如果您在代码中使用文字 0,您仍然会遇到此问题,是的,它会影响重载解析。

0 以外的值,即使是整数文字,也永远不是空指针常量,因此不能隐式转换为指针。这也适用于值为 1true。因此,重载决策可能会受到作为参数传递的特定值的影响。

空指针常量使 NULL 可以初始化和比较空指针,方法是 NULL 扩展为值为 0 的整数文字或 nullptr.从 C++11 开始,后者是一个替代的空指针常量。

您的意图是通过将 指针 传递给这些值以测试函数来测试布尔值和整数值。但是,当您调用测试函数(pbpv)时,您无意中没有为这些值提供 指针

test(false); // error C2668: 'test' : ambiguous call to overloaded function
test(true); // error C2664: 'test' : cannot convert parameter 1 from 'bool' to 'bool *'

在 C 和 C++ 中,类型提升将允许 false 被视为 NULL (nullptr),因为 false 的值为 0。这对于 true 是不允许的,因为 true值为 1.

第一个错误是由于编译器无法决定你想调用哪个test()(因为你正在传递 nullptr(一个所谓的空指针常量类型) 在这两种情况下。

第二个错误是由于编译器不允许允许您将参数转换为指针。