【发布时间】:2017-02-25 23:40:14
【问题描述】:
我正在设计一种具有共享所有权语义的容器类型。它支持切片,因此切片共享所有权。我的问题之一是数据共享似乎会干扰 const 的正确性,所以我试图注意这一点,但我对结果不满意。
以下是我的实际代码的一个大大分解的版本:
#include <memory>
#include <vector>
#include <algorithm>
template <typename T>
class SharedMem
{
public:
SharedMem(std::initializer_list<T> init)
: m_mem(std::make_shared<std::vector<T>>(init.begin(), init.end()))
, m_data(m_mem->data())
, m_size(m_mem->size())
{ }
SharedMem(SharedMem& other) = default; // best-effort for copy-construction
SharedMem(SharedMem const& other) = delete; // disallow, would circumvent const-correctness
SharedMem& operator = (SharedMem const& other) {
std::copy(other.m_data, other.m_data + other.m_size, m_data);
return *this;
}
std::size_t size() const
{ return m_size; }
T& operator [] (std::size_t index)
{ return m_data[index]; }
T const& operator [] (std::size_t index) const
{ return m_data[index]; }
SharedMem slice(std::size_t first, std::size_t last) {
SharedMem<T> ret(*this);
ret.m_data += first;
ret.m_size = last - first;
return ret;
}
SharedMem const slice(std::size_t first, std::size_t last) const {
SharedMem<T> ret(*this);
ret.m_data += first;
ret.m_size = last - first;
return ret;
}
private:
std::shared_ptr<std::vector<T>> m_mem; // shared underlying memory
T* m_data; // start of slice
std::size_t m_size; // size of slice
};
预期用途:
int main(int argc, char** argv) {
SharedMem<int> a { 0, 1, 2, 3, 4 };
SharedMem<int> b { 8, 9 };
SharedMem<int> c = a; // shallow copy of a, data is shared
a.slice(1, 3) = b; // a = [0, 8, 9, 3, 4]
c[4] = 6; // a = [0, 8, 9, 3, 6]
}
有些东西告诉我我走错了路。我发现我的方法存在以下问题:
- 它违反了规则 3。我特别不喜欢为了修复 const 正确性而禁用默认复制构造函数的需要。否则,可以创建 const 对象的非常量副本,而后者可以修改前者的元素。
- 复制构造和赋值实现了非常不同的操作。这就是我如何让
c = a和a.slice(1, 3) = b做正确的事情(实际上是非常不同的事情)。
我不确定我是否遇到了麻烦。问题:
- 这种设计是否可行,还是会在未来引起问题?如果有,是哪个?
- 如果存在严重缺陷,如何修复/避免?
感谢任何提示。
【问题讨论】:
-
这个赋值似乎被破坏了,因为它可以写出包含范围的边界。
-
@Kerrek SB:当然。正如我所写,代码已尽可能简化。实际代码长度超过 1000 行,具有更复杂的切片、相应的迭代器和其他功能。它还检查边界:)
标签: c++ containers const-correctness