5

我被告知要避免在 C++ 中使用指针。但是在我尝试编写的代码中,我似乎无法避免它们,或者我可能错过了其他出色的 C++ 功能。

我希望创建一个包含另一个类 (class2) 作为数据成员的类 (class1)。然后我希望 class2 了解 class1 并能够与之通信。

我可以引用 class1 作为 class2 中的成员,但这意味着我需要提供对 class1 的引用作为 class2 的构造函数中的参数,并使用我不想要的初始化列表。我试图在不需要构造函数的情况下做到这一点。

我希望 class2 有一个名为 Initialise 的成员函数,它可以接受对 class1 的引用,但如果不使用指针,这似乎是不可能的。人们会在这里推荐什么?提前致谢。

代码完全简化只是为了了解主要思想:

class class1
{
    public:
        InitialiseClass2()
        {
            c2.Initialise(this);
        }

    private:
        class2 c2;

};

class class2
{
    public:
        Initialise(class1* c1)
        {
            this->c1 = c1;
        }

    private:
        class1* c1;

};
4

5 回答 5

6

如果不使用指针,这似乎是不可能的

这是不正确的。实际上,要处理对其他对象的引用,请将引用引入构造函数:

class class2
{
    public:
        class2(class1& c1)
           : c1(c1)
        {}

    private:
        class1& c1;
};

这里的关键是初始化而不是分配引用。这是否可能取决于您是否可以摆脱您的Initialise功能并适应 RAII(请这样做!)。之后,这是否真的是一个好主意取决于您的用例;如今,您几乎可以肯定地通过使用其中一种智能指针类型来使所有权和生命周期语义更加清晰——即使它只是一个std::weak_ptr.

无论如何,说得更笼统。

指针“总是”不好吗?不,当然不是。我几乎想说自己管理动态内存“总是”不好,但我不会一概而论。

你应该避开它们吗?是的。

不同之处在于后者是引导您远离手动内存管理的指南,而前者是一种尝试性的禁止。

于 2015-10-15T13:43:52.073 回答
4

不,在 C++ 中使用指针一点也不差,我一遍又一遍地看到这种反建议。不好的是自己管理指针,除非您正在创建指针管理低级实体。

再次,我将作出非常明确的区分。使用指针很好。很少有真正的 C++ 程序可以不用 USING 指针。管理指针是不好的,除非你正在使用指针管理器。

于 2015-10-15T13:37:42.697 回答
3

指针可以是nullptr,而引用必须始终绑定到某些东西(并且不能随后重新绑定到其他东西)。

这是您的设计选择的主要区别和主要考虑因素。

指针的内存管理可以委托给适当的std::shared_ptrstd::unique_ptr

于 2015-10-15T13:40:40.293 回答
0

首先,每当您的设计中有循环依赖时,请三思而后行,并确保它是可行的方法。尝试使用依赖倒置原则来分析和修复你的依赖。

我被告知要避免在 C++ 中使用指针。但是在我尝试编写的代码中,我似乎无法避免它们,或者我可能错过了其他出色的 C++ 功能。

指针是一种强大的编程工具。与 C++(或任何一般编程语言)中的任何其他特性一样,当它们是正确的工具时,它们必须被使用。在 C++ 中,您还可以访问与使用中的指针类似但语法更好的引用。此外,它们不能为空。因此它们总是引用一个有效的对象。

因此,当您需要时使用指针,但尽量避免使用原始指针,并尽可能选择智能指针作为替代方案。这将保护您免受一些微不足道的内存泄漏问题,但您仍然必须注意您的对象生命周期,并且对于每个动态分配的对象,您应该清楚地知道谁创建它以及何时/谁将释放为对象分配的内存。

指针(和引用)通常非常有用,因为它们可用于通过引用将参数传递给方法,因此您可以避免在堆栈中按值传递重对象。例如,假设您有一个非常大的重对象数组(其中 copy/= 运算符很耗时)并且您想对这些对象进行排序。一种简单的方法是使用指向这些对象的指针,因此您只需移动非常轻量级数据类型的指针(基本上是机器地址的大小),而不是在排序操作期间移动整个对象。

于 2015-10-15T14:14:53.690 回答
0

好吧,我从来不需要 2 个类来相互参考,并且有充分的理由,你怎么知道如何测试这些类?如果稍后您需要更改 2 个类的通信方式,您可能必须更改两个类中的代码)。您可以通过多种方式解决

  1. 您实际上可能只需要 1 节课(您已经分成了很多节课)
  2. 您可以为一个类注册一个观察者(使用第三个类,在这种情况下,您最终会得到一个指针,但至少这两个类的耦合度较低,并且更容易测试它们)。
  3. 您可以考虑(也许)一个只需要一个类来调用另一个类的方法的新接口
  4. 您可以将 lambda(或者如果您没有 C++11,则为仿函数)传递给该类的方法之一,从而无需反向引用
  5. 您可以在方法内传递类的引用。
  6. 也许你只需要很少的课,实际上你需要第三课而不是与两个课交流。
  7. 您可能需要一个访客(也许您真的需要多次调度)

上面的一些解决方法需要指针,有些不需要。给你选择;)

注意:但是你所做的对我来说完全没问题(我看到你只在构造函数中做了一些诡计,但可能你有更多省略的代码,在这种情况下会给你带来麻烦)。在我的情况下,我将一个类“注册”到另一个类中,然后在调用构造函数之后,我只有一个类调用另一个类,反之亦然。

于 2015-10-15T13:58:17.890 回答