作为数据成员指向 const 对象的指针

Pointer to const object as a data member

根据 IsoCpp 上的 C++ 最佳实践,我们不应该有 const 或引用数据成员:C.12: Don’t make data members const or references

但它没有指定是否允许指向 const 对象的指针。考虑这个例子:

class Connection {
    gsl::not_null<const Network*> m_network;
    ...

public:
    [[nodiscard]] const Network* getNetwork() const;
    ...
}

// Implementation
const Network* Connection::getNetwork() const {
    return m_network;
}

它是否仍然符合所描述的最佳实践?指针不是 const 但指针指向的数据是

我们是否应该从成员声明中删除 const 但仍将 getter return 类型标记为指向 const 的指针?

是的,你可以

如果您有 const 数据成员,则删除复制和移动构造函数。但这只适用于指针本身是常量,而不是指向的值。

const &const * 仅在 class 不可复制时才合适(例如某种“经理 class”)

视情况而定。

此建议存在的原因是使您的类型可复制和可分配,并且两者具有匹配的语义。

所以考虑一下:

struct Connection {
  Network const& network;
  /**/
};

复制这个很好,对吧?但随后分配休息时间,因为 network 将不可重新安排。

所以在这种情况下,将该成员替换为例如std::shared_ptr<Network const> 没问题。大概几个连接可以使用同一个网络。

但是——如果您不想共享但每个对象都有自己的成员副本,那么您只能在赋值时重建该成员,因为无法更改旧对象。取决于可能不是你想要做的对象。

例如:

struct Connection {
  std::shared_ptr<Network const> network;
  std::unique_ptr<std::vector<Entry> const> properties;
};

除了 pointer-to-vector 是错误的形式(无缘无故的双重间接寻址)。重新构造向量需要分配新的内存,而仅重用旧的则不需要(假设分配了足够的内存)。

诚然,这是一个构造示例,可能有一种方法可以解决这个问题。但重点是,您的复制和赋值的相似性将在很大程度上取决于成员对象的复制和赋值的质量

在这种情况下,适用于没有指针的情况的相同推理同样适用于有指针的情况。您必须决定这是否适合您的类型。


但是,我认为并非每个类型 都必须 是可分配的。您可以有意识地决定拥有一个无法分配给的类型。然后,只有这样,才有一个没有任何间接寻址的 const 成员。