首先查看我遇到的问题,然后查看我的用例(我可能误用了
std::unique_ptr
,所以我想添加一个关于我实际想要做什么的注释)。
我正在尝试找到一种方法来支持遵守
std::unique_ptr
。也就是说,有一个非拥有函数将接收 std::unique_ptr
的内容,但无法修改其任何组件。直观的模式是编写一个采用 const T*
对象的函数,然后使用 MyUniquePtr.get()
调用该函数。但这会导致以下有问题的片段:
#include <memory>
struct unique_wrapper
{
unique_wrapper(std::unique_ptr<int>&& m) : m(std::move(m))
{}
std::unique_ptr<int> m;
};
void foo(const unique_wrapper* w)
{
// PROBLEM CODE
*(w->m) = 5;
}
int main()
{
auto unique_squared = std::make_unique<unique_wrapper>(std::make_unique<int>(0));
foo(unique_squared.get());
}
上面的代码片段真的让我害怕,因为我们完全违反了
std::unique_ptr
关于拥有单一所有者的保证。
因此这引出了我的问题:在 C++ 中共享数据同时保证一方不会修改数据的自然方式是什么?
我有一个应该有一个所有者的数据结构,但我们希望将这个单个对象传递给多个观察方,这些观察方不会获得它的所有权(因为所有者仍然有工作要做),但肯定需要访问它的内容
auto object = acquire_resources();
// don't want to transfer object ownership!
validate_object_state(object);
// use object further
...
你的问题是常量正确性。公开指针(包括智能指针)的类不是常量正确的。通过将
m
设为私有并公开 operator*
和 operator->
来使其常量正确:
struct unique_wrapper {
unique_wrapper(std::unique_ptr<int>&& m) : m(std::move(m)) {}
// add non-const versions only if unique_wrapper is meant to modify data as non-const
int& operator*() noexcept { return *m; }
const int& operator*() const noexcept { return *m; }
// operator-> is not very useful for pointer of int, but I guess your real problem is more complex
int* operator->() noexcept { return m.get(); }
const int* operator->() const noexcept { return m.get(); }
private:
std::unique_ptr<int> m;
};
void foo(const unique_wrapper* w)
{
**w = 5; // error, it's const
}
void bar(unique_wrapper* w)
{
**w = 5; // fine, can modify
}