使用 std::unique_ptr 实现持续遵守

问题描述 投票:0回答:1

首先查看我遇到的问题,然后查看我的用例(我可能误用了

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
...
c++ smart-pointers unique-ptr
1个回答
0
投票

你的问题是常量正确性。公开指针(包括智能指针)的类不是常量正确的。通过将

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
}

在线查看

© www.soinside.com 2019 - 2024. All rights reserved.