6

我有一个这样定义的函数:

void doSomethingWithCustomer (const Customer &customer);

我的一位开发人员这样称呼它:

Customer *customer = order.getCustomer();
doSomethingWithCustomer (*customer);

不幸的是getCustomer,如果订单未绑定到客户,该方法可能会返回 nullptr。如果getCustomer返回 nullptr,则应用程序不会在调用时崩溃,doSomethingWithCustomer而是在使用客户参考的函数内崩溃。

当然,正确的写法是先检查 customer 不是 nullptr,然后如果我们有有效的客户,则调用该函数。通常我们期望如果一个函数/方法有一个引用参数,调用者检查它的有效性(这里不是这种情况),而不是函数本身检查参数。

我知道 Visual Studio 2010(及更早版本)通过实际传递指针来传递引用,但我想知道这是否在 C++ 标准中的某处指示。我们是否可以假设引用总是作为指针传递(就我个人而言,我不会依赖这个,但知道它很有趣)?

是否可以告诉 Visual Studio 在传递引用时,它应该首先自动取消引用并在调用时崩溃,而不是在更深的地方(在调试版本中这样做可能就足够了)?

4

6 回答 6

4

假设引用作为指针传递是否有效?

不它不是。
该标准不要求引用应该以指针的形式实现。

如何实际实现引用是标准留给实现决定的实现细节。它仅描述来自参考的预期行为,其中之一是参考永远不能NULL在标准符合程序中。

如果您的函数参数NULL有时会出现,那么您应该将其作为指针传递。

于 2012-11-20T09:30:26.067 回答
1

It's not observable, and it's irrelevant. A program using this code has undefined behavior because it dereferences a null pointer.

于 2012-11-20T13:18:03.840 回答
1

不,它完全由实现定义。

出于诊断目的,我创建了一个小容器类型来验证参数。然后,您将声明函数/方法:

void doSomethingWithCustomer(const t_nonnull<const Customer>& pCustomer);

其中t_nonnull类型在构造时验证了参数。但是,我发现越来越频繁地使用引用更有用(IOW,在这种情况下不要返回指针 - 只需将在客户不存在时访问客户视为错误)。

于 2012-11-20T09:34:15.057 回答
1

行为未定义。这意味着您不能依赖任何特定的方式来发现错误。一个好的编译器可能会在编译时警告您,而另一个可能会完全掩盖错误,具体取决于您使用变量的方式。您有责任确保引用永远不会为 NULL。

于 2012-11-20T09:37:16.767 回答
0

引用可以在内部使用指针来实现(就像在 Java 中发生的那样)。但以下两个区别是它们之间的关键:

  1. 默认情况下,指针可以重新绑定到另一个对象。然而,引用与它被初始化的对象具有永久绑定
  2. 指针可以赋值为 0,但引用不能

类比T&等价于T* const

您无需通知编译器有关延迟变量的信息,因为这是您自己发生的。

void foo(T&);

T t, *p = 0;
foo(t); // the only way to pass reference
foo(*p); // the only way to pass reference
于 2012-11-20T09:28:42.077 回答
0

正如其他人所说,该标准并未规定应如何实施引用。要及早捕获“取消引用的 NULL 作为引用传递”错误,您可以在函数中执行此操作:

void doSomethingWithCustomer (const Customer &customer)
{
  assert(&customer);
  //... rest of function
}
于 2012-11-20T09:55:24.003 回答