如何在C++中使用空引用及该或不该

Darksun2010

不该!大家别看了。

问题场景

假设我们自己实现了一个system函数,用于代替C标准库下面的那个,目的是增强多平台的统一性。Windows实现下的system()1的尿性,大家也是知道的。

思考再三,函数原型如下:

bool system(const std::string& command, int& exitCode);

其中返回值标志是否运行正确,exitCode引用则负责带回该命令的返回值。
然后遇到了这样一个程序,它的返回值对程序的逻辑无关痛痒,所以可以根本不要这个exitCode

解决方案

最脏的办法,就是传一个无用的int类型变量,调用完后边搁在一边。就算g++不抱怨unused,作为强迫症的我们也看不过去这无端多出来的一个无用变量。
很好,接下来有两条路。

使用指针

C语言中也常常有这种情况,这时候我们多半会想到空指针。只要传一个空指针,并在运行时判断是否为NULL以选择是否写入即可。遂把函数原型改成:

bool system(const std::string& command, int* exitCode);

一切貌似都解决了,指针近乎野蛮地强行为我们开出了一条道路。
但我们是直男癌,阿不,引用癌啊。怎么容许高贵的C++代码里出现指针的身影。

为什么不想想空引用

先看一段标准里的对于引用的说明

A reference shall be initialized to refer to a valid object or function. [Note: in particular, a null reference cannot exist in a well-defined program, because the only way to create such a reference would be to bind it to the “object” obtained by dereferencing a null pointer, which causes undefined behavior. As described in 9.6, a reference cannot be bound directly to a bitfield. ]
—ISO/IEC 14882:1998(E), the ISO C++ standard, in section 8.3.2 [dcl.ref]

嗯哼,标准貌似对我们这种意图实现空引用的行为不予支持。在标准中,任何对空引用的操作行为都是未定义行为。但是想想,我们可以通过引用的地址判断其是否有效,于是可以回避这些行为。
判断方法很简单:

if (&ref != nullptr)
    //do something

于是我们要开始用奇技淫巧革命了。

创建及使用一个空引用

为了方便创建不同类型的空引用,最好以模板函数的方式实现:

template<typename T>
T& createNullRef() { return *static_cast<T*>(nullptr); }

并以如下方式食用:

system("echo no null ref?", createNullRef<int>());

Voila! 实现方法就是这么简单。

这样真的好么

抛开个人信仰不谈,与标准背道而驰,使用空引用而不是空指针来忽略掉多余的参数,真的是个好方法么?
个人认为,在开发团队都使用这一做法时,这样的方法并没有什么不妥,原因如下:

  1. 统一,system(str1, &exitCode)system(str1, exitCode)相比,后者明显更优。
  2. 简单,在函数内部只需要几个合法性判断,而不像指针那样需要*->
  3. C++不就是用来玩的么,这么纠结这一问题为什么不使用golang呢。
  4. 我真的很喜欢引用啊。

至少,本弱开发的wTest里使用的就是这一方法。但本人也不知道自己会不会在某一时刻推翻我自己此时的想法。

So,be prudence.


  1. 在Windows下,system()只是做一个调用其他程序的工作,只要调用成功就返回0,不成功就返回-1,无法通过其获取程序返回值。
阅读 8.8k

avaicode
各种胡扯
55 声望
0 粉丝
0 条评论
55 声望
0 粉丝
文章目录
宣传栏