据我所知,引用不能为空,但是当我运行这样的代码时:
#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())
,它将无法编译。
答案 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作为第一个参数传递会导致未定义行为。