【问题标题】:Setting std::string to 0 during definition vs setting std::string to 0在定义期间将 std::string 设置为 0 与将 std::string 设置为 0
【发布时间】:2016-02-15 19:46:19
【问题描述】:

我正在处理我的一个项目,并且在为类创建构造函数时,我正在将一些变量设置为默认值。我将std::string 设置为NULL,它给了我一个错误。但是,当我在同一行定义 std::string 并将其设置为 NULL 时,它可以正常工作而不会出现任何错误。我想知道为什么

第一个例子

std::string text = NULL;

工作,并且

第二个例子

std::string text;
text = NULL;

没用。现在我知道你不应该将字符串设置为 NULL 或 0,但我偶然发现了这一点。

第一个示例是否调用了一个采用char* 的构造函数,并认为 0 是指向 char 的指针?我认为= 也调用了构造函数,所以我不明白为什么它们不能同时工作,除非std::string 专门重载= 运算符。

我正在使用 Microsoft Visual Studio Express 2013

【问题讨论】:

  • std::string text = NULL; 行你没有遇到运行时错误吗?
  • @mnciitbhu 不,我正在使用 Visual Studio 2013 Express。完全没有错误。
  • @mnciitbhu 所以两者之间显然存在某种差异

标签: c++ string constructor


【解决方案1】:

NULL 的值计算为 0

现在,std::string text = NULL; 将调用构造函数采用const char* 并尝试复制数据,但由于NULL 没有指向任何内容,因此在运行时会发生错误,我得到了(使用 gcc 5.2 ) :

terminate called after throwing an instance of 'std::logic_error'
  what():  basic_string::_M_construct null not valid

由于没有为std::stringint(或size_t)定义operator=text = NULL; 将无法编译。

【讨论】:

  • 但是= 不会再次调用size_t ctor 吗?
  • @GregM 它调用赋值运算符。这有点令人困惑,但是在初始化的上下文中使用 operator= 会调用一个隐式构造函数,而在初始化后调用一个赋值运算符。
  • 确实如此,但它变得毛茸茸的地方是隐式构造。例如,如果你有隐式:Foo(int x),并且没有为 int 重载赋值运算符,那么尝试这样做:Foo f; f = 123; ... 实际上会调用 Foo 的参数化构造函数来隐式构造它,然后隐式生成分配Foo& operator=(const Foo&);
  • @GregM:基本上,是的。在性能方面,只要语义不改变,编译器就可以做捷径(即就地创建“临时”,或者——从 C++11 开始——移动构造它。)这个想法是,因为没有办法将int赋值Foo,编译器寻找替代方案,发现可以将Foo赋值给Foo 可以从int构造一个Foo,这就是它的作用。
  • @GregM 您可以通过删除复制构造函数来检查是否也使用了复制构造函数,并检查是否有任何错误。见ideone.com/nLke48
【解决方案2】:

第二次分配的原因

text = NULL;

在 VC++ 编译器错误消息中。它说:

错误 C2593:“操作员 =”不明确 可能是 'std::basic_string &std::basic_string::operator =(const _Elem)' 或 'std::basic_string &std::basic_string::operator =(const _Elem *const )'

稍微分解一下,上面写着:

错误 C2593:“操作员 =”不明确 可能是 'std::string &std::string::operator =(const char)' 或'std::string &std::string::operator =(const char *const)'

所以它不起作用是因为编译器不确定0 是一个char 值,还是const char*

如果您在 0 周围使用单引号将其转换为 char 值,它将编译:

text = '\0'; // NULL or can use any other character

或者如果你将它转换为指针类型

type = (const char*)NULL; // Crashes, but now we're sure what type 0 is meant to be

这也将编译。请记住,将std::string 分配给NULL 指针会在尝试从NULL 复制字符时崩溃。

【讨论】:

  • 沿着这些思路,第一个构造函数起作用的原因是因为没有构造函数接受单个 char,但有一个接受 const char*,因此将 NULL 传递给构造函数没有歧义(只是未定义的行为)。
  • 是的,接受charstd::string fill constructor 还需要一个int 参数,用于使用多少char(它是std::string(int, char)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-01-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多