【问题标题】:Initializing a reference to member to NULL in C++在 C++ 中初始化对成员的引用为 NULL
【发布时间】:2012-01-29 18:56:08
【问题描述】:

是否可以在 c++ 中将引用成员初始化为 NULL?
我正在尝试这样的事情:

class BigClass
{
private:
  Object m_inner;
public:
  const Object& ReadOnly;
  BigClass() : ReadOnly(NULL)
  {
    Do stuff.
  }
};

我知道如果我将“ReadOnly”初始化为一个对象的真实引用,我可以做到这一点,但是当我想在那里输入“NULL”时,我得到了错误:

"无法从 'int' 转换为 'const Object &'

我该如何解决这个问题?

【问题讨论】:

  • 参考的目的是使这成为不可能。请改用常规指针。
  • 你可以这样做 { const Object& ReadOnly = *(Object*)NULL; } 但它的丑陋。预处理器只是删除 & 和 *
  • @Justin "预处理器只是去掉了 & 和 *" 废话
  • @curiousguy 哼哼……让我详细说明仇恨者。预处理器取消 *& 组合。使用 ref & 声明只是简写,因此您不需要使用 -> 它是 (*the).thing 的简写。所以那里;)
  • @Justin C++ 预处理器不做这样的事情。

标签: c++ reference initialization-list


【解决方案1】:

不,C++ 中的引用不能是 NULL1

可能的解决方案包括:

  • 使用指针而不是引用。
  • 有一个虚拟的Object 实例,可以用来表示“没有对象”。

[1] 来自C++11 standard:

[dcl.ref] [...] 空引用不能存在于定义明确的程序中,因为创建此类引用的唯一方法是将其绑定到通过取消引用空指针获得的“对象”,这会导致未定义的行为。

【讨论】:

  • @Magnus:是的,不要这样做,这是未定义的行为。
  • @wandalen - 哪一部分?
  • @OliverCharlesworth 参考并不是什么神奇的事情。引用可以指向 NULL。例如:Object& object = (Object) NULL.
  • @wandalen - 这不会编译。
  • @OliverCharlesworth Object& object = * ( Object * ) NULL
【解决方案2】:

你无法“解决”这个问题。如果您希望该成员不指向任何内容,请使用指针。

引用必须初始化为真实对象,它们不能“无处指向”。

【讨论】:

  • @EthanSteinberg:取决于。智能指针通常涉及所有权。有时你只是想指向某些东西而不声称拥有所有权。当然你可以使用弱指针,但这需要在堆上分配对象:没有堆栈分配的对象,没有更大对象的属性,等等... 智能指针是 NOT灵丹妙药.
【解决方案3】:

可以做到,但几乎可以肯定这是一个非常糟糕的主意。这样做的方法是取消引用一个适当类型的 NULL 指针,这已经表明这是一个坏主意:此时您会遇到未定义的行为,但是通常倾向于“工作”。

在 C++ 中,引用总是指一个实际的对象。这与其他编程语言不同,其中“引用”实际上相当于 C++ 中的 pointers(通常没有指针算术之类的东西)。您可能真正想要的(不幸的是,您没有说出您试图实现的目标,而是询问了可能是被误导的方法的一部分的问题的解决方案)是使用指针:

Object const* const readOnly;
BigClass(): readOnly(0) {}

【讨论】:

  • 我最喜欢的答案。我只需要调试一个复杂的类,并且需要使用某个对象调用单个函数。 0 引用了所描述的所有引用,构造了 obj,忽略了引用,调用了函数,修复了问题,撤消了所有内容。显然不是你想要永久做的事情。
【解决方案4】:

它在编写单元测试时很有用。这是唯一应该完成的地方,但在那里,它非常有帮助。

 Bar& bar(*static_cast<Bar*>(0));
 MockClass mock; // derives from RealClass
 mock.foo(bar);

在这里,我正在测试使用 MockClass 的代码,而不是 MockClass 本身。

它不是灵丹妙药,但它可以提供帮助。此外,GoogleMock 可能是你的朋友,如果你在模拟“具体”类。

struct Bar;
struct RealClass {
  int& x_;
  double& y_;
  RealClass(int& x, double& y) :x_(x), y_(y) {}
  virtual void foo(Bar&);
};
struct MockClass: public RealClass {
  MockClass(): RealClass(*(int*)0, *(double*)0) {}
  MOCK_METHOD1(foo, void(Bar&));
};

【讨论】:

  • Down-voters:尝试使用对 NULL 的引用不使用。非常困难!如果不是很明显,我们的目标是测试使用RealClass 并在RealClass 上调用foo() 的代码。我们注入RealClassBar 实例。 MockClass 需要调用RealClass 的构造函数,但永远不需要底层数据。这是一个有效的用例,所以停止投票。
  • 如果你需要写这种测试,我认为你有一个严重的设计问题。
  • 遗留代码与否,在单元测试中引入未定义的行为是一个糟糕的想法。
  • 这不是未定义的行为。它回答了这个问题。否决问题,而不是答案。
  • 感谢@cdunn2001!这对于使用 GTKmm 模拟单元测试我的应用程序非常有帮助。
【解决方案5】:

使用指针:- const Object* pReadOnly;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-04-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-17
    • 1970-01-01
    相关资源
    最近更新 更多