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 != NULL
或pb != false
都可以,但更好的是if(pb)
MSVC 将表达式 false
视为 空指针常量 .
空指针常量可以隐式转换为任何指针类型,从而产生空指针值。
根据标准,正确的行为是仅将值为 0
的整数文字视为空指针常量。虽然它有值 0
,但 false
不是整数文字。
然而,此规则仅在 CWG issue 903 决议后生效。在此之前,每个值为 0
的整型常量表达式都是空指针常量。
MSVC 没有使用默认标志实现缺陷报告,仍然遵循这个旧规则,根据该规则,表达式 false
是一个空指针常量。
如果您给 MSVC 标志 /permissive-
使其表现得更符合标准并实施新规则。对于 /std:c++20
或更高版本,这也是默认设置,如果我没记错的话。
但是请注意,如果您在代码中使用文字 0
,您仍然会遇到此问题,是的,它会影响重载解析。
除 0
以外的值,即使是整数文字,也永远不是空指针常量,因此不能隐式转换为指针。这也适用于值为 1
的 true
。因此,重载决策可能会受到作为参数传递的特定值的影响。
空指针常量使 NULL
可以初始化和比较空指针,方法是 NULL
扩展为值为 0
的整数文字或 nullptr
.从 C++11 开始,后者是一个替代的空指针常量。
您的意图是通过将 指针 传递给这些值以测试函数来测试布尔值和整数值。但是,当您调用测试函数(pb
和 pv
)时,您无意中没有为这些值提供 指针 。
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(一个所谓的空指针常量类型) 在这两种情况下。
第二个错误是由于编译器不允许允许您将参数转换为指针。
我在 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 != NULL
或pb != false
都可以,但更好的是if(pb)
MSVC 将表达式 false
视为 空指针常量 .
空指针常量可以隐式转换为任何指针类型,从而产生空指针值。
根据标准,正确的行为是仅将值为 0
的整数文字视为空指针常量。虽然它有值 0
,但 false
不是整数文字。
然而,此规则仅在 CWG issue 903 决议后生效。在此之前,每个值为 0
的整型常量表达式都是空指针常量。
MSVC 没有使用默认标志实现缺陷报告,仍然遵循这个旧规则,根据该规则,表达式 false
是一个空指针常量。
如果您给 MSVC 标志 /permissive-
使其表现得更符合标准并实施新规则。对于 /std:c++20
或更高版本,这也是默认设置,如果我没记错的话。
但是请注意,如果您在代码中使用文字 0
,您仍然会遇到此问题,是的,它会影响重载解析。
除 0
以外的值,即使是整数文字,也永远不是空指针常量,因此不能隐式转换为指针。这也适用于值为 1
的 true
。因此,重载决策可能会受到作为参数传递的特定值的影响。
空指针常量使 NULL
可以初始化和比较空指针,方法是 NULL
扩展为值为 0
的整数文字或 nullptr
.从 C++11 开始,后者是一个替代的空指针常量。
您的意图是通过将 指针 传递给这些值以测试函数来测试布尔值和整数值。但是,当您调用测试函数(pb
和 pv
)时,您无意中没有为这些值提供 指针 。
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(一个所谓的空指针常量类型) 在这两种情况下。
第二个错误是由于编译器不允许允许您将参数转换为指针。