首页 > 解决方案 > 堆分配对象的设置器

问题描述

建议有一个由堆中分配的对象组成的类。

class A
{
public:
    A() { m_b = new B; m_c = new C; }
    virtual ~A() { delete m_b; delete m_c; }

    inline B* b() const { return m_b; }
    inline C* c() const { return m_c; }

private:
    B* m_b;
    C* m_c;
}

哪些设置器最适合此类代码?

这个我想通了

inline void setB(B* b) const { delete m_b; m_b = b; }
inline void setC(C* c) const { delete m_c; m_c = c; }

但是有一个问题。如果我们添加了一个非堆变量或者只是一个我们不必用这个 setter 删除的变量,它将在下一次调用 setter 后被删除,这种情况会导致错误或意外行为。

我们也不能直接删除对象,因为 getter 有const修饰符。此外,它也不安全,因为该类的用户可能不知道内部对象是否在堆中分配。

您能否解释一下如何将 setter 与堆分配的对象一起使用?

标签: c++memorymemory-managementheap-memorygetter-setter

解决方案


不要使用原始newdelete. 改用智能指针——它们更安全、更容易使用。在您的情况下,std::unique_ptr看起来像一个不错的候选人:

class A
{
public:
    A() : m_b{std::make_unique<B>()}, m_c{std::make_unique<C>()} { }
    virtual ~A() = default;

    inline B* b() const { return m_b.get(); }
    inline C* c() const { return m_c.get(); }

private:
    std::unique_ptr<B> m_b;
    std::unique_ptr<C> m_c;
}

然后,您的二传手可以简单地是:

void setB(std::unique_ptr<B>&& b) { m_b = std::move(b); }
void setC(std::unique_ptr<C>&& c) { m_c = std::move(c); }

推荐阅读