为什么可以将 nullptr 赋给 std::string?

问题描述 投票:0回答:2

所以今天我写了一个相当难发现的错误,其中我将 std::string 初始化为 nullptr (不是指向 std::string 的指针,而是值本身)。我发现显然只能在 C++11 或更高版本中使用 clang 来完成。

#include <string>
#include <iostream>

using namespace std;
class Meh{
    int x;
};
class Foo
{
private:
  std::string x=nullptr;
  Meh y=nullptr; //remove this line and it compiles
public:
  std::string z=nullptr;
};

int main(void)
{
    Foo f;
    cout << f.z;
    return 0;
}

如您所见,我尝试将 nullptr 分配给类的随机实例,但它不起作用。字符串中有什么魔力可以让它发挥作用,这甚至是有效的语法?我认为在这种情况下我会遇到类型转换错误。

作为参考,我用这个编译了:

clang++ test.cpp -O3 -g -fno-inline -std=c++11 -Wall

它没有给出任何形式的警告,但如果不使用 C++11 则会出错

c++ string c++11 standards
2个回答
14
投票

这只是因为std::string构造函数

(链接中的数字(5))和
赋值运算符(链接中的数字(3))接受
const char*
,因此
nullptr 
匹配。

在 C++11 之前(因此在

nullptr
之前),当您尝试从
0
NULL
进行构造时,也会出现同样的问题。所有这些情况都是非法的,并导致未定义的行为,尽管至少有一个 STL(RogueWave?)过去接受了它并生成了一个空字符串。


0
投票

从 C++23 开始,

std::string x = nullptr;
的格式不正确。它最初起作用的原因是因为 构造函数接受
const CharT*
,它也可能是
nullptr
:

basic_string( const CharT* s, const Allocator& alloc = Allocator() );

但是,此构造函数在重载决策中输给了新构造函数:

basic_string( std::nullptr_t ) = delete;

如果您尝试用 C++23 编译代码,您将收到编译器错误。在 C++11 中,运行代码将是未定义的行为。 由于允许

= nullptr
毫无意义,因为它始终是一个错误,因此 P2166:禁止 nullptr 的 std::basic_string 和 std::basic_string_view 构造的提案建议禁止它。

© www.soinside.com 2019 - 2024. All rights reserved.