返回空字符串文字 VS。返回 nullptr - 它们是否相同?
Returning an empty string literal VS. returning a nullptr - Are they the same?
我最近在我开发的应用程序的 public SDK 中发现了以下功能:
virtual char* ExtentName() {return "";}
当我使用带有 /permissive-
标志的 Visual Studio 编译应用程序时,上面的函数导致以下编译错误:
error C2440: 'return': cannot convert from 'const char [1]' to 'char *'
note: Conversion from string literal loses const qualifier (see /Zc:strictStrings)
我真的很惊讶这段代码在任何情况下都能编译,因为它将字符串文字(在本例中为空终止符)转换为 char*
。这怎么可能?
此外,我想在不导致 SDK 中断的情况下解决此问题。这是我认为最好的解决方案:
virtual char* ExtentName() {return nullptr;}
上面的更改不会破坏 ABI,但我担心它会破坏我们用户的代码,尽管我不确定如何破坏。有这种可能吗?感谢您提供任何信息!
自 C++11 以来,禁止在没有 const
限定的情况下将字符串文字隐式转换为 char*
。
MSVC 无论如何都允许它向后兼容,因为早期版本的 C++ 允许它。 /permissive-
标志使其行为符合标准。
第一个函数 return 不是一个空指针值,它 return 是一个指向字符串文字的有效指针,它将是一个长度为 char
的数组 1
仅包含空终止符。因此这两个功能完全不相等。
第二个函数 return 是一个空指针值,与第一个函数的 return 值相比,可以例如不能间接通过。
从技术上讲,您可以通过显式 const_cast
:
来保留函数签名
virtual char* ExtentName() { return const_cast<char*>(""); }
它本身具有明确定义的行为,但是任何尝试写入从该函数 returned 的指针指向的数组都将导致未定义的行为,而编译器不会发出警告。
因此不应该这样做。但是,如果您已经针对以前的 C++ 标准或许可编译器编译了原始函数,那么该函数已经做到了这一点,并且不会引入任何 new UB 风险。通过 returned 指针写入在原始代码中也将是 UB 而没有警告。
正确的做法是使 return 值 const char*
,因为显然不允许用户修改此函数指向的值 return。可能从一开始就没有这样做是个错误。
不,它们根本不一样。目前,函数 return 是指向 c 字符串的有效指针,大概在所有情况下都是如此。如果您将其更改为 sometimes return a nullptr
,任何依赖有效性而不检查中断的代码。
理想情况下,您会 return 一个 std::string
,但这需要使用该函数更改代码。
将函数更改为return一个const char*
。这将清楚地表明此 c 字符串是 const
。这只有 "breaks" 代码错误地假定它不是 const
,但这是一件好事,因为 c 字符串 是 const
.
如果无法更改 ABI,请保持原样。
我最近在我开发的应用程序的 public SDK 中发现了以下功能:
virtual char* ExtentName() {return "";}
当我使用带有 /permissive-
标志的 Visual Studio 编译应用程序时,上面的函数导致以下编译错误:
error C2440: 'return': cannot convert from 'const char [1]' to 'char *'
note: Conversion from string literal loses const qualifier (see /Zc:strictStrings)
我真的很惊讶这段代码在任何情况下都能编译,因为它将字符串文字(在本例中为空终止符)转换为 char*
。这怎么可能?
此外,我想在不导致 SDK 中断的情况下解决此问题。这是我认为最好的解决方案:
virtual char* ExtentName() {return nullptr;}
上面的更改不会破坏 ABI,但我担心它会破坏我们用户的代码,尽管我不确定如何破坏。有这种可能吗?感谢您提供任何信息!
自 C++11 以来,禁止在没有 const
限定的情况下将字符串文字隐式转换为 char*
。
MSVC 无论如何都允许它向后兼容,因为早期版本的 C++ 允许它。 /permissive-
标志使其行为符合标准。
第一个函数 return 不是一个空指针值,它 return 是一个指向字符串文字的有效指针,它将是一个长度为 char
的数组 1
仅包含空终止符。因此这两个功能完全不相等。
第二个函数 return 是一个空指针值,与第一个函数的 return 值相比,可以例如不能间接通过。
从技术上讲,您可以通过显式 const_cast
:
virtual char* ExtentName() { return const_cast<char*>(""); }
它本身具有明确定义的行为,但是任何尝试写入从该函数 returned 的指针指向的数组都将导致未定义的行为,而编译器不会发出警告。
因此不应该这样做。但是,如果您已经针对以前的 C++ 标准或许可编译器编译了原始函数,那么该函数已经做到了这一点,并且不会引入任何 new UB 风险。通过 returned 指针写入在原始代码中也将是 UB 而没有警告。
正确的做法是使 return 值 const char*
,因为显然不允许用户修改此函数指向的值 return。可能从一开始就没有这样做是个错误。
不,它们根本不一样。目前,函数 return 是指向 c 字符串的有效指针,大概在所有情况下都是如此。如果您将其更改为 sometimes return a nullptr
,任何依赖有效性而不检查中断的代码。
理想情况下,您会 return 一个 std::string
,但这需要使用该函数更改代码。
将函数更改为return一个const char*
。这将清楚地表明此 c 字符串是 const
。这只有 "breaks" 代码错误地假定它不是 const
,但这是一件好事,因为 c 字符串 是 const
.
如果无法更改 ABI,请保持原样。