使用指针成员类/对象变量更好吗?

时间:2016-05-17 06:42:59

标签: c++

当我试图保留一个关于#includes的干净头文件时,我发现我可以通过让所有成员指向需要包含其他头文件的类/对象来做得更好,因为这样我可以使用前向声明而不是#includes。

但我开始怀疑这是否是一个很好的经验法则。

例如,参加以下课程 - 选项1:

class QAudioDeviceInfo;
class QAudioInput;
class QIODevice;

class QAudioRx
{
public:
    QAudioRx();
private:  
    QAudioDeviceInfo *mp_audioDeviceInfo;
    QAudioInput *mp_audioInput;
    QIODevice *mp_inputDevice;
};

然而,这可以像这样重写 - 选项2:

#include "QAudioDeviceInfo.h"
#include "QAudioInput.h"
#include "QIODevice.h"

class QAudioRx
{
public:
    QAudioRx();
private:  
    QAudioDeviceInfo m_audioDeviceInfo;
    QAudioInput m_audioInput;
    QIODevice m_inputDevice;
};

选项1,通常是我的偏好,因为它包含更好的清洁标题。但是,选项2不需要动态分配/解除资源分配。

也许这可以看作是一个主观/基于意见的问题(而且我知道意见 - 警察将全部都是这个),所以让我们避免“我喜欢”和“我更喜欢”并坚持事实/关键 - 分。

所以我的问题是,一般来说,最佳实践(如果有的话)是什么?为什么?或者,如果没有一个最佳实践(通常是这种情况),何时使用每个实践都很好?

修改

抱歉,这真的是针对私人变量 - 而非公开变量。

3 个答案:

答案 0 :(得分:4)

如果需要指针,请使用指针。指针不是为了避免包含。包括不是邪恶的。当您需要使用它们时,请使用它们。简单的规则等于快乐编程!

在你的情况下使用指针会带来很多不必要的开销。您可能必须动态分配您的对象,这对您的案例来说不是一个好选择。您还必须手动处理内存管理。简单地说,没有理由在这里使用指针,除非你的情况要求(例如你希望对象比指针本身更多地存活(例如非所有权模式)。

答案 1 :(得分:2)

在编译时和编译时依赖关系(通常与所需的包含文件数量相关)和简单性和效率之间存在权衡。

选项1编译速度更快,但几乎肯定会运行得更慢。每次访问成员变量时,都会通过指针进行间接寻址,并且必须分别分配和管理指针引用的对象。如果分配是动态的,则需要额外的成本,而管理单独对象的额外逻辑可能会引入错误。首先你有原始指针,所以你必须定义(或删除)一个复制构造函数,复制赋值,可能还有析构函数,也许移动构造函数和移动赋值(你的例子缺少所有这些,因此可能会被严重破坏)

选项2需要一些额外的包含,因此当任何标题更改时,需要重新编译使用QAudioRx的所有内容。这使QAudioRx与其他类型紧密相关。在一个可能很重要的大型项目中(但在一个小项目中它可能并不重要 - 如果构建整个项目的时间是在几秒钟内测量的话,那肯定是不值得的!)

但是我会说你的选择1几乎不是一个好主意。如果您关心减少依赖关系和构建时间,请使用pImpl idiom(另请参阅相关问题):

class QAudioRx
{
public:
    QAudioRx();

private:  
    class QAudioRxImpl;
    std::unique_ptr<QAudioRxImpl> m_impl;
};

(N.B。我使用std::unique_ptr<QAudioRx>假设impl对象将被动态分配,因为这是最常用的方法,如果对象管理方式不同,则可以调整解决方案。

现在所有成员变量都是“impl”对象的一部分,该对象未在标题中定义。这意味着从impl类中访问成员是直接的,而不是通过指针,但是QAudioRx的访问必须执行一个间接调用来调用impl类上的函数。

这仍然减少了依赖性,但是由于没有原始指针,因此管理额外的复杂性变得更加简单,因此特殊成员函数将自动执行某些操作。默认情况下,它将是可移动的,但不可复制,并将在析构函数中清理。

答案 2 :(得分:1)

当你在小型项目上工作时,课程数量很少,那么你应该选择2。

但是当您处理非常大的项目时,其中项目的数量非常大,项目的编译时间是开发项目架构的标准之一,那么请选择选项1.

在大多数情况下,选项1很好。在实际应用程序中,您需要结合使用此选项,选择编译时间和代码的漂亮外观之间的交易(没有指针和对象的nacked new(动态分配)。)