我遇到了这段代码:
void f(const std::string &s);
接一个电话:
f( *((std::string*)NULL) );
我想知道其他人对这种结构的看法,它用于表示函数f()应该使用一些默认值(它计算)而不是一些用户提供的值。
我不知道该怎么想,它看起来很奇怪,但你怎么看待这种结构?
答案 0 :(得分:53)
没有。它是未定义的行为,可能导致代码执行任何操作(包括重新格式化硬盘,核心转储或侮辱您的母亲)。
如果您需要能够传递NULL,那么使用指针。采用引用的代码可以假定它引用了一个有效的对象。
附录:C ++ 03标准(ISO / IEC 14882,2 nd edition 2003)在§8.3.2“参考文献”第4段中说:
应初始化引用以引用有效对象 或功能。 [注意:特别是,在明确定义的程序中不能存在空引用,因为仅 创建这样一个引用的方法是将它绑定到通过解除引用空指针获得的“对象”, 导致未定义的行为。如9.6中所述,引用不能直接绑定到位字段。 ]
[加重强调]
答案 1 :(得分:16)
你有时会在相当深奥的模板库代码中看到这样的结构,但只能在sizeof()
里面看到它是无害的。
假设您想知道函数类型F
的返回类型的大小,如果它传递了对类型T
的引用作为参数(两者都是模板参数) 。你可以写:
sizeof(F(T()))
但是如果T恰好没有公共默认构造函数呢?所以你这样做了:
sizeof(F(*((T *)0)))
传递给sizeof
的表达式从不执行 - 它只是被分析到编译器知道结果大小的位置。
答案 2 :(得分:5)
我很好奇 - 函数'f'实际检查这个条件吗?因为如果它没有,并且它试图使用该字符串,那么当你尝试使用它时,这显然会崩溃。
如果'f'检查引用为NULL,那为什么不只是使用指针?是否存在一些严格而快速的规则,你不会使用指针而某些傻瓜在不考虑其含义的情况下是否遵守了法律的规定?
我只想知道...
答案 3 :(得分:3)
使用NULL引用是否正确?
不,除非你不喜欢你的老板和你的工作;)
这非常糟糕。它最重要的参考点之一 不能为NULL(除非你强制它)
答案 4 :(得分:3)
对于你可以制作“空对象”的情况,它将扮演零指针
的角色class Foo
{
static Foo empty;
public:
static bool isEmpty( const Foo& ref )
{
return &ref==∅
}
}
答案 5 :(得分:2)
正如其他人已经说过的那样:参考必须是有效的。这就是为什么它是一个引用而不是一个指针。
如果你想让f()有一个默认行为,你可能想要使用它:
static const std::string default_for_f;
void f(const std::string &s = default_for_f)
{
if (&s == &default_for_f)
{
// make default processing
}
else
...
}
...
void bar()
{
f(); // call with default behavior
f(default_for_f); // call with default behavior
f(std::string()); // call with other behavior
}
您可以为f()省略默认参数。 (有些人讨厌默认参数。)
答案 6 :(得分:1)
f( *((std::string*)NULL) );
这实际上是解除引用NULL,在大多数系统上#defined为0.最后我检查了0x00000000是一个无效内存地址,用于执行任何操作。
无论发生什么事只是检查
if (std::string.length() > 0) ....