const std :: string&s = nullptr如何作为可选参数

时间:2019-05-06 08:22:10

标签: c++ reference stdstring initializer nullptr

据我所知,引用不能为空,但是当我运行这样的代码时:

#include <iostream>
#include <string>

void test(int i, const std::string& s = nullptr) {
  std::cout << i << " " << s << std::endl;
}

int main() {
  test(1, "test");
  test(2);
}

可选参数s可以为null,并构建代码。此外,当test(2)运行时,程序将引发异常,而不是打印一些随机字符串。

当我将s更改为诸如int之类的基本类型时,它未能编译,因此我认为魔术仍然保留在字符串类中,但是如何?

此外,如何检查s是否为null?如果我使用if(s==nullptr)if(s.empty()),它将无法编译。

2 个答案:

答案 0 :(得分:11)

test通过使用std::basic_string<char>的构造函数number 5初始化其参数:

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

因为它需要具体化一个临时(std::string)才能绑定到该引用。那是因为引用必须绑定到正确类型的对象,而std::nullptr_t不是。所述构造函数对要传递的指针具有 not null 约束。在没有显式参数的情况下调用test会导致行为未定义。

非常清楚,在格式良好的C ++程序中没有空引用之类的东西。引用必须绑定到有效对象。尝试使用nullptr初始化一个只会发现进行转换。

由于std::string是具有明确定义的“空”状态的对象,因此固定版本可以简单地传入默认的初始化字符串:

void test(int i, const std::string& s = {}); // Empty string by default.

一旦违反合同得到解决,s.empty()应该会再次给出有意义的结果。

答案 1 :(得分:4)

引用确实不能为null,但是const std::string& s = nulltr并没有按照您的想象做。如果未指定第二个参数,则编译器将创建一个字符串对象,该对象调用implicit字符串构造函数,该构造函数将指向以null结尾的字符串的指针作为第一个参数。因此test(2);调用看起来像这样:

test(2, ::std::string(static_cast<char const *>(nullptr), ::std::string::allocator_type()));

请注意,将nullptr作为第一个参数传递会导致未定义行为。