什么时候最好将数据成员存储为引用而不是指针?

时间:2009-06-05 17:23:02

标签: c++ tdd reference mocking pointers

假设我有一个包含数据库连接数据成员的对象Employee_Storage。该数据成员是应该存储为指针还是作为参考?

  • 如果我将它存储为参考,我    不必做NULL    检查。 (无论如何,NULL检查有多重要?)

  • 如果我将它存储为指针,那就是       更容易设置Employee_Storage       (或MockEmployee_Storage)       测试目的。

一般来说,我一直习惯于将我的数据成员存储为引用。但是,这使得我的模拟对象难以设置,因为我现在必须传入true / mock对象,而不是传递NULL s(大概是在默认构造函数中)。

是否有良好的经验法则可以遵循,特别关注可测试性?

5 个答案:

答案 0 :(得分:14)

如果在构造中分配引用作为数据成员,则最好将它们存储起来,并且确实没有理由改变它们。由于无法重新分配引用,因此它们非常有限。

通常,我通常存储为指针(或某种形式的模板化智能指针)。这更灵活 - 既可用于测试(如您所述),也可用于正常使用。

答案 1 :(得分:8)

将引用存储为数据成员几乎从不优先,并且很多时候它是不可能的。如果对象必须是可分配的(因为它们必须存储在标准库容器中),则不能使用引用。此外,无法重新引用引用,因此一旦使用对象初始化引用,就无法引用其他对象。

有关此问题的详细讨论,请参阅此问题Should I prefer pointers or references in member data?

答案 2 :(得分:3)

我试图自己解决这个问题,所以不妨发布它。我得出结论,使用引用数据成员似乎不是一个好主意,因为在初始化它时可能会无意中创建别名。

#include <iostream>
using namespace std;
class stuff
{
public:
explicit stuff(int &a):x(a) //you have to initialize it here
{
//body intialization won't work
};
int& x; //reference data member
};

int main()
{
int A=100; 
stuff B(A);//intialize B.x
cout<<B.x<<endl;//outputs 100
A=50;//change A;
cout<<B.x<<endl; //outputs 50, so B.x is an alias of A.
system("pause");
return 0;
}

答案 3 :(得分:2)

如果有选择,我喜欢尽可能使用最受约束的类型。 因此,如果我不需要支持null对象,我更愿意声明

Foo& m_foo;

成员而不是

Foo*const m_foo;

成员,因为前一个声明记录了m_foo不能为空的事实。 从短期来看,优势并不是那么好。但是从长远来看,当你回到旧代码时,即时保证你不必担心m_foo为空的情况是非常有价值的。

还有其他方法可以达到类似的效果。我在他们不理解引用的地方工作的一个项目会坚持任何潜在的空指针都加上'00',例如m_foo00。有趣的是,boost::optional似乎support references虽然我没有尝试过。或者您可以使用断言来丢弃代码。

答案 4 :(得分:0)

添加到此问题。

具有参考数据成员的类:

  • 您必须将一个值传递给构造对象(不要意外)
  • 违反了封装规则,因为可以从外部类更改引用变量,而无需类对象对其进行任何控制。 (出于某些非常特殊的原因,我想唯一的用例可能是这样的。)
  • 防止创建分配运算符。您要复制什么?
  • 您需要确保在对象运行时不会破坏所引用的变量