在C ++中检查空对象

时间:2010-01-20 08:16:56

标签: c++ object null

我大部分时间都只使用过C语言,并且遇到了一些C ++中一些不熟悉的问题。

假设我在C中有这样的函数,这是非常典型的:

int some_c_function(const char* var)
{
    if (var == NULL) {
        /* Exit early so we don't dereference a null pointer */
    }
    /* The rest of the code */
}

让我们说我正在尝试用C ++编写类似的函数:

int some_cpp_function(const some_object& str)
{
    if (str == NULL)  // This doesn't compile, probably because some_object doesn't overload the == operator

    if (&str == NULL) // This compiles, but it doesn't work, and does this even mean anything?
}

基本上,我所要做的就是在使用NULL调用some_cpp_function()时防止程序崩溃。

  • 使用对象C ++执行此操作的最典型/常用方法是什么(不涉及重载==运算符)?

  • 这是否是正确的做法?也就是说,我不应该编写将对象作为参数的函数,而是编写成员函数吗? (但即使如此,请回答原来的问题)

  • 在一个引用一个对象的函数或一个采用C风格指针指向一个对象的函数之间,是否有理由选择一个而不是另一个?

8 个答案:

答案 0 :(得分:33)

  

基本上,我所要做的就是   防止程序崩溃时   调用some_cpp_function()   NULL。

无法使用NULL调用该函数。获得引用的目的之一是,它总是指向某个对象,因为在定义它时必须对其进行初始化。不要将引用视为花哨指针,将其视为对象本身的别名。然后就不会出现这种混乱。

答案 1 :(得分:14)

引用不能为NULL。界面使您可以将真实对象传递给函数。

因此无需测试NULL。这是将引用引入C ++的原因之一。

注意你仍然可以编写一个带指针的函数。在这种情况下,您仍然需要测试NULL。如果值为NULL,那么就像在C中一样提前返回。注意:当指针为NULL时,不应该使用异常。如果参数永远不应为NULL,则创建一个使用引用的接口。

答案 2 :(得分:5)

C ++引用不是指针也不是Java / C#样式引用,不能为NULL。它们表现得好像是另一个现有对象的别名。

在某些情况下,如果您的代码中存在错误,您可能会获得对已经死亡或不存在的对象的引用,但您可以做的最好的事情是希望程序很快就会死掉以便能够调试发生了什么以及为什么你的程序被破坏了。

也就是说,我已经看到“null引用”的代码检查执行类似于:if ( &reference == 0 )的操作,但标准清楚地表明在格式良好的程序中不能有空引用。如果引用绑定到空对象,则程序格式错误,应予以纠正。如果需要可选值,请使用指针(或某些更高级别的构造,如boost::optional),而不是引用。

答案 3 :(得分:5)

正如大家所说,引用不能为空。这是因为,引用是指对象。在您的代码中:

// this compiles, but doesn't work, and does this even mean anything?
if (&str == NULL)

您正在获取对象str的地址。根据定义,str存在,因此它有一个地址。所以,它不能是NULL。因此,从语法上讲,上述内容是正确的,但从逻辑上讲,if条件总是错误的。

关于您的问题:这取决于您想要做什么。你想让函数能够修改参数吗?如果是,请传递参考。如果没有,请不要(或传递对const的引用)。有关详细信息,请参阅this C++ FAQ

通常,在C ++中,大多数人都喜欢通过引用传递指针。其中一个原因正是您发现的:引用不能是NULL,因此避免了您在函数中检查它的麻烦。

答案 4 :(得分:4)

如果引用如下,您可以使用特殊的指定对象作为空对象:

class SomeClass
{
    public:

        int operator==(SomeClass &object)
        {
            if(this == &object) 
            {
                    return true;
            }

            return false;
        }


    static SomeClass NullObject;
};

SomeClass SomeClass::NullObject;

void print(SomeClass &val)
{
    if(val == SomeClass::NullObject)
    {
        printf("\nNULL");
    }
    else
    {
        printf("\nNOT NULL");
    }
}

答案 5 :(得分:2)

您应该仅将NULL用于指针。您的函数接受引用,它们不能为NULL。

编写函数就像在C中编写函数一样。

答案 6 :(得分:2)

C ++引用自然不能为null,您不需要检查。只能通过传递对现有对象的引用来调用该函数。

答案 7 :(得分:2)

  
      
  • 使用对象C ++(不涉及重载==运算符)执行此操作的最典型/常用方法是什么?
  •   
  • 这是否是正确的方法?即。我不应该编写以对象作为参数的函数,而是编写成员函数吗? (但即便如此,请回答原来的问题。)
  •   

不,引用不能为空(除非已经发生未定义的行为,在这种情况下所有的赌注都已经关闭)。是否应该编写方法或非方法取决于其他因素。

  
      
  • 在一个引用一个对象的函数或一个采用C风格指针指向一个对象的函数之间,是否有理由选择一个而不是另一个?
  •   

如果需要表示“无对象”,则将指针传递给该函数,并使该指针为NULL:

int silly_sum(int const* pa=0, int const* pb=0, int const* pc=0) {
  /* Take up to three ints and return the sum of any supplied values.

  Pass null pointers for "not supplied".

  This is NOT an example of good code.
  */
  if (!pa && (pb || pc)) return silly_sum(pb, pc);
  if (!pb && pc) return silly_sum(pa, pc);
  if (pc) return silly_sum(pa, pb) + *pc;
  if (pa && pb) return *pa + *pb;
  if (pa) return *pa;
  if (pb) return *pb;
  return 0;
}

int main() {
  int a = 1, b = 2, c = 3;
  cout << silly_sum(&a, &b, &c) << '\n';
  cout << silly_sum(&a, &b) << '\n';
  cout << silly_sum(&a) << '\n';
  cout << silly_sum(0, &b, &c) << '\n';
  cout << silly_sum(&a, 0, &c) << '\n';
  cout << silly_sum(0, 0, &c) << '\n';
  return 0;
}

如果“无对象”永远不需要表示,那么引用工作正常。实际上,运算符重载更简单,因为它们会超载。

你可以使用像boost :: optional。

这样的东西