检查 C++ 中的空对象

发布于 2024-08-18 10:39:03 字数 865 浏览 1 评论 0原文

我主要只使用 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 风格指针指向对象的函数之间,是否有理由选择其中一个?

I've mostly only worked with C and am running into some unfamiliar issues in C++.

Let's say that I have some function like this in C, which would be very typical:

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 */
}

And let's say that I'm trying to write a similar function in 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?
}

Basically, all I'm trying to do is to prevent the program from crashing when some_cpp_function() is called with NULL.

  • What is the most typical/common way of doing this with an object C++ (that doesn't involve overloading the == operator)?

  • Is this even the right approach? That is, should I not write functions that take an object as an argument, but rather, write member functions? (but even if so, please answer the original question)

  • Between a function that takes a reference to an object, or a function that takes a C-style pointer to an object, are there reasons to choose one over the other?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

瑶笙 2024-08-25 10:39:03

基本上,我想做的就是
防止程序崩溃时
some_cpp_function() 被调用
空。

无法使用 NULL 调用该函数。拥有引用的目的之一是,它将始终指向某个对象,因为您必须在定义它时初始化它。不要将引用视为花哨的指针,而应将其视为对象本身的别名。那么这种混乱就不会出现。

Basically, all I'm trying to do is to
prevent the program from crashing when
some_cpp_function() is called with
NULL.

It is not possible to call the function with NULL. One of the purpose of having the reference, it will point to some object always as you have to initialize it when defining it. Do not think reference as a fancy pointer, think of it as an alias name for the object itself. Then this type of confusion will not arise.

狼性发作 2024-08-25 10:39:03

引用不能为 NULL。该接口使您可以将真实的对象传递给函数。

所以不需要测试NULL。这是 C++ 中引入引用的原因之一。

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

A reference can not be NULL. The interface makes you pass a real object into the function.

So there is no need to test for NULL. This is one of the reasons that references were introduced into C++.

Note you can still write a function that takes a pointer. In this situation you still need to test for NULL. If the value is NULL then you return early just like in C. Note: You should not be using exceptions when a pointer is NULL. If a parameter should never be NULL then you create an interface that uses a reference.

維他命╮ 2024-08-25 10:39:03

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

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

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

A C++ reference is not a pointer nor a Java/C# style reference and cannot be NULL. They behave as if they were an alias to another existing object.

In some cases, if there are bugs in your code, you might get a reference into an already dead or non-existent object, but the best thing you can do is hope that the program dies soon enough to be able to debug what happened and why your program got corrupted.

That is, I have seen code checking for 'null references' doing something like: if ( &reference == 0 ), but the standard is clear that there cannot be null references in a well-formed program. If a reference is bound to a null object the program is ill-formed and should be corrected. If you need optional values, use pointers (or some higher level construct like boost::optional), not references.

放我走吧 2024-08-25 10:39:03

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

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

您正在获取对象 str 的地址。根据定义,str 存在,因此它有一个地址。因此,它不能为NULL。因此,从语法上讲,上面是正确的,但从逻辑上讲,if 条件始终为假。

关于你的问题:这取决于你想做什么。您希望函数能够修改参数吗?如果是,请传递参考。如果不是,则不要(或传递对 const 的引用)。请参阅此 C++ 常见问题解答了解一些详细信息。

一般来说,在 C++ 中,大多数人更喜欢通过引用传递而不是传递指针。原因之一正是您所发现的:引用不能为 NULL,从而避免您在函数中检查它的麻烦。

As everyone said, references can't be null. That is because, a reference refers to an object. In your code:

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

you are taking the address of the object str. By definition, str exists, so it has an address. So, it cannot be NULL. So, syntactically, the above is correct, but logically, the if condition is always going to be false.

About your questions: it depends upon what you want to do. Do you want the function to be able to modify the argument? If yes, pass a reference. If not, don't (or pass reference to const). See this C++ FAQ for some good details.

In general, in C++, passing by reference is preferred by most people over passing a pointer. One of the reasons is exactly what you discovered: a reference can't be NULL, thus avoiding you the headache of checking for it in the function.

没企图 2024-08-25 10:39:03

在引用的情况下,您可以使用特殊的指定对象作为空对象,如下所示:

class SomeClass {
    public:
        int operator==(SomeClass &object) {
            return (this == &object);
        }

    static SomeClass NullObject;
};

SomeClass SomeClass::NullObject;

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

You can use a special designated object as the null object in case of references as follows:

class SomeClass {
    public:
        int operator==(SomeClass &object) {
            return (this == &object);
        }

    static SomeClass NullObject;
};

SomeClass SomeClass::NullObject;

void print(SomeClass &val) {
    if(val == SomeClass::NullObject)
        printf("\nNULL");
    else
        printf("\nNOT NULL");
}
固执像三岁 2024-08-25 10:39:03

您只能将 NULL 与指针一起使用。您的函数接受引用,并且它们不能为 NULL。

就像用 C 语言编写函数一样编写函数。

You should use NULL only with pointers. Your function accepts a reference and they can't be NULL.

Write your function just like you would write it in C.

意中人 2024-08-25 10:39:03

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

C++ references naturally can't be null, you don't need the check. The function can only be called by passing a reference to an existing object.

等风也等你 2024-08-25 10:39:03
  • 使用对象 C++ 执行此操作的最典型/常见方法是什么(不涉及重载 == 运算符)?
  • 这是正确的方法吗? IE。我不应该编写以对象作为参数的函数,而是编写成员函数吗? (但即使是这样,请回答原来的问题。)

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

  • 在采用对象引用的函数或采用 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 的东西。

  • What is the most typical/common way of doing this with an object C++ (that doesn't involve overloading the == operator)?
  • Is this even the right approach? ie. should I not write functions that take an object as an argument, but rather, write member functions? (But even if so, please answer the original question.)

No, references cannot be null (unless Undefined Behavior has already happened, in which case all bets are already off). Whether you should write a method or non-method depends on other factors.

  • Between a function that takes a reference to an object, or a function that takes a C-style pointer to an object, are there reasons to choose one over the other?

If you need to represent "no object", then pass a pointer to the function, and let that pointer be 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;
}

If "no object" never needs to be represented, then references work fine. In fact, operator overloads are much simpler because they take overloads.

You can use something like boost::optional.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文