C++11 向后兼容性(空整数常量到指针的转换)
C++11 backwards compatibility (conversion of null integer constant to pointer)
C++ 标准允许将零整数常量隐式转换为任何类型的指针。
以下代码无效,因为这里的值v
不是常量:
float* foo()
{
int v = 0;
return v; // Error
}
但是下面的代码是正确的:
float* foo()
{
const int v = 0;
return v; // Ok in C++98 mode, error in C++11 mode
}
问题是:为什么gcc
和clang
(试过不同的版本)在c++98/03模式下编译代码正确但是return warning/error 在 c++11/14 模式下编译时 (-std=c++11
)?我试图找到 C++11 工作草案 PDF 中的更改,但没有成功。
Intel 编译器 16.0 和 VS2015 编译器在这两种情况下均未显示任何错误和警告。
GCC 和 Clang 与 -std=c++11
的行为不同,因为 C++11 更改了空指针常量的定义,然后 C++14 再次更改了它,请参阅 Core DR 903 更改了C++14 中的规则,因此只有文字是空指针常量。
在 C++03 4.10 [conv.ptr] 中说:
A null pointer constant is an integral constant expression (5.19) rvalue of integer type that evaluates to zero.
这允许各种表达式,只要它们是常量且计算结果为零即可。枚举、false
、(5 - 5)
等等......这曾经在 C++03 代码中引起很多问题。
在 C++11 中它说:
A null pointer constant is an integral constant expression (5.19) prvalue of integer type that evaluates to zero or a prvalue of type std::nullptr_t
.
在 C++14 中它说:
A null pointer constant is an integer literal (2.14.2) with value zero or a prvalue of type std::nullptr_t
.
这是一个更严格的规则,也更有意义。
C++ 标准允许将零整数常量隐式转换为任何类型的指针。
以下代码无效,因为这里的值v
不是常量:
float* foo()
{
int v = 0;
return v; // Error
}
但是下面的代码是正确的:
float* foo()
{
const int v = 0;
return v; // Ok in C++98 mode, error in C++11 mode
}
问题是:为什么gcc
和clang
(试过不同的版本)在c++98/03模式下编译代码正确但是return warning/error 在 c++11/14 模式下编译时 (-std=c++11
)?我试图找到 C++11 工作草案 PDF 中的更改,但没有成功。
Intel 编译器 16.0 和 VS2015 编译器在这两种情况下均未显示任何错误和警告。
GCC 和 Clang 与 -std=c++11
的行为不同,因为 C++11 更改了空指针常量的定义,然后 C++14 再次更改了它,请参阅 Core DR 903 更改了C++14 中的规则,因此只有文字是空指针常量。
在 C++03 4.10 [conv.ptr] 中说:
A null pointer constant is an integral constant expression (5.19) rvalue of integer type that evaluates to zero.
这允许各种表达式,只要它们是常量且计算结果为零即可。枚举、false
、(5 - 5)
等等......这曾经在 C++03 代码中引起很多问题。
在 C++11 中它说:
A null pointer constant is an integral constant expression (5.19) prvalue of integer type that evaluates to zero or a prvalue of type
std::nullptr_t
.
在 C++14 中它说:
A null pointer constant is an integer literal (2.14.2) with value zero or a prvalue of type
std::nullptr_t
.
这是一个更严格的规则,也更有意义。