【问题标题】:Why isn't it a compile-time error to return a nullptr as a std::string?为什么将 nullptr 作为 std::string 返回不是编译时错误?
【发布时间】:2019-06-17 11:38:02
【问题描述】:

由于一个错误,我刚刚发现这段代码在 Visual Studio 17 上编译得很好,而且可能在其他编译器上也是如此。现在我很好奇为什么?

#include <iostream>
#include <string>

std::string foo(){
    return nullptr;
}

int main(){
    auto s = foo();
    std::cout << s << std::endl;
}

我可以想象这是因为std::basic_string c'tor 可以使用char* 调用,并且在返回从ptr 到std::string 的隐式转换时发生(使用NULL 作为参数,然后发出嘘声)。我走对了吗?

【问题讨论】:

标签: c++ function language-lawyer stdstring


【解决方案1】:

是的,你的假设是正确的,检查std::basic_string constructors #5 将被调用:

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

请注意,传递nullptr 会调用the standard 和注释中所述的未定义行为:

行为是 如果[s, s + Traits::length(s)) 不是有效范围,则未定义(对于 例如,如果s 是一个空指针)。

【讨论】:

  • 有趣的是,std::string_view 的构造函数有 attribute__((__nonnull)) 并且当 NULL 或 nullptr 被传递给 std::string_view 的构造函数时编译器会发出警告。我想知道,为什么 std::string 的构造函数没有这样的属性
【解决方案2】:

为什么不编译? std::string 具有以下构造函数:

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

构造字符串,其内容由s 指向的空终止字符串的副本初始化。构造函数是显式的,因此从nullptrstd::string 的隐式转换确实是可能的。

【讨论】:

  • 请注意传递null是UB
  • @RichardCritten,绝对是。但问题是为什么这段代码会编译,而不是如果代码被执行会发生什么。 UB 不仅会发生在 nullptr 上,而且会发生在任何不指向以 null 结尾的字符串开头的指针。
猜你喜欢
  • 2012-10-19
  • 2016-01-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-26
  • 1970-01-01
  • 2014-06-27
  • 1970-01-01
相关资源
最近更新 更多