【问题标题】:c++ class defining. attributes as pointers? which is the correct way? [duplicate]c++ 类定义。属性作为指针?哪个是正确的方法? [复制]
【发布时间】:2012-11-01 13:48:38
【问题描述】:

可能重复:
C++ - when should I use a pointer member in a class

我已经使用 c++ 多年,但我仍然有一些问题我没有回答。 我正在定义一个 c++ 类,但对此我有一些疑问

问题1:我应该使用指针存储投资还是不使用?

Investment* investment;
// or
Investment investment;

问题 2:为什么?

问题 3:如果我使用 Investment investment;,我是否应该以这种方式返回引用 Investment & getInvestment();

我知道我的代码的两种方式都可以工作,但我想知道执行此操作的有效方式..

代码如下:

class Urgency
{
private:
    Investment* investment;
public:
    Urgency(Investment* investment);
    ~Urgency(void);

    Investment* getInvestment();
};

【问题讨论】:

  • @jogojapan 我已经看到了这个问题,但我还有其他问题没有得到解答。请参阅问题 2 和 3。谢谢
  • 我相信问题 2(“为什么?”)是由重复的问题回答的,尽管在一个非常笼统的层面上。如果您需要更具体的答案,您必须提供更多关于 Investment 类是什么、做什么以及如何使用它的详细信息。问题 3 实际上可能证明一个完全独立的帖子是合理的(如果也有重复,我不会感到惊讶)。
  • @jogojapan 抱歉,但我不同意你的观点。我准备了一个问题,我认为可以更全面地澄清这些疑虑。

标签: c++ class pointers reference


【解决方案1】:

我通常更喜欢在对象较大时使用指针,而在对象较小时使用堆栈对象。指针允许一些事情,例如惰性初始化和前向声明,而堆栈对象减少了您需要创建自己的复制构造函数以及不必担心显式销毁析构函数中的对象的可能性。 (虽然,您可以使用共享指针类型对象来为您执行此操作)此外,堆栈对象通常访问速度更快,但在大多数情况下,这不应该成为选择一个而不是另一个作为大多数差异的原因应用程序可以忽略不计。

参考您的代码,您通常会返回一个const Investment &,以不允许直接修改投资对象。如上所述,如果您使用原始指针,您应该创建一个复制构造函数和一个析构函数来正确管理对象上的内存。对于指针对象,您通常会再次返回 const Investment * 以消除外部调用者直接修改您的对象的能力。

当您返回 const 正确的 Investment 对象时,请注意您的函数是如何在 Investment 类中声明的。如果您只是拥有Investment::getNumShares(),您将无法使用 const 引用或 const 指针访问该函数。要解决此问题,请将所有不修改对象的成员函数标记为 const,例如Investment::getNumShares() const

【讨论】:

    【解决方案2】:
    1. 不要使用指针,除非你绝对需要它们
    2. 因为如果不小心使用它们很容易出错
    3. 更好的是,如果您不打算让所有人更改您的Investment,请返回const &

    【讨论】:

      【解决方案3】:

      问题 1/2:我应该使用指针存储投资还是不使用? / 为什么?

      Investment* investment;
      // or
      Investment investment;
      

      各有利弊。

      不使用指针:

      • 省去了担心创建和删除投资对象的麻烦 - 尽管如果有用,您可以在初始化列表中显式选择投资构造函数。
      • 表示投资对象是在宿主对象内分配的,可以省去一次堆的分配和释放。这可能会更节省内存并且性能更好。

      使用指针:

      • 允许您使用延迟初始化:您可以推迟创建投资对象,直到包含的对象真正需要它,然后可能在不再需要时再次删除它。这种对生命周期的手动控制可用于微调内存使用情况。当指针不指向实际投资时,在指针中存储 NULL/0 是帮助跟踪这一点的常见做法。
      • 意味着您可以将 Investment 对象的所有权授予您的对象之外的代码...他们可以继续使用它并在适当的时候将其删除。
      • 意味着您必须精心设计一个复制构造函数,并小心处理构造函数中的异常。智能指针可能有助于解决这些问题。
      • 意味着您可以分配从 Investment 派生的类的实例,并通过相同的指针使用它。这使您可以选择适合您的运行时需要的自定义实现,甚至可以根据需要改变实现。这种灵活性是面向对象编程和运行时多态性的基石。
      • 意味着包含对象的标头只需要查看(无论是通过#include 还是在同一文件中)投资类的前向声明。这意味着可以对 Investment 对象进行更改,而无需强制重新编译仅使用包含对象的代码(只需重新链接包含修改后的 Investment 实现的对象)。该概念与指向实现的指针或 pImpl 惯用语相同,但投资不一定是包含类的实现的专用部分,并且可以在程序的其他地方直接且独立地使用。

      问题3:如果我使用投资投资;我应该以这种方式返回参考投资 & getInvestment();?

      这在很大程度上取决于程序。有时最好避免直接暴露数据成员,而是在包含对象中提供更高级别的逻辑函数,该函数对投资做一些工作:这样你就可以在投资对象周围维护额外的不变量——即你可以控制、协调和监控何时以及如何使用它。其他时候,暴露它可能更实际。

      仅当您可以确定您实际上有要返回的投资对象时才适合返回引用:在您的指针版本中,实现可能需要创建/new 一个投资对象(如果它还没有)一。或者,返回指针意味着您可以向客户端代码返回 NULL/0 以指示您还没有投资对象,但是您必须确保您的类和客户端代码了解谁将拥有持续所有权(即delete 投资对象的权利/义务),并且双方都不会在对方 deleted 之后尝试使用投资。

      【讨论】:

        【解决方案4】:
        • 通过使用指针,您可以选择何时分配内存以及 删除它,而普通声明具有自动存储。要回答这个问题,这实际上取决于您编写的程序类型和个人喜好。

          class Foo
          {
              Foo* Obj; //choose when to allocate this object, dynamically allocated
              Foo Obj2; //automatic, runs through the life of the object.
          }
          
        • 您可以,但分配地址的另一种解决方案是使用带有参数的 void 函数,该参数设置对象的引用。

          void GetVar(int *Address_Holder)
              {
                  //assign address
              }
          

        【讨论】:

          【解决方案5】:

          如果你想控制什么时候给一个对象分配内存以及什么时候删除它,那么就使用指针。如果你有一个巨大的对象,那么使用指针作为传递函数的指针将比传递对象本身更快(或者你可以通过引用传递)。在任何其他情况下,建议使用对象而不是指针,因为使用指针很容易出错。

          【讨论】:

            猜你喜欢
            • 2016-09-25
            • 1970-01-01
            • 2012-12-03
            • 1970-01-01
            • 2016-05-20
            • 2023-01-28
            • 2021-11-01
            • 2017-04-05
            • 2012-06-18
            相关资源
            最近更新 更多