将对象从局部变量移动到 std::shared_ptr

发布于 2025-01-14 04:09:01 字数 1343 浏览 3 评论 0原文

请注意,标题中的“对象”和“移动”一词并不是指 C++ 特定的对象是什么以及移动对象意味着什么的概念。

我有一个非常简单的结构类型的局部变量,我在其中累积从配置文件读取的一些值。

struct Foo
{
    std::string name;
    float someValue;
    int someStuff;
};

// This stores the current settings
std::shared_ptr<Foo> currentFooSetting;

void readSettings()
{
    Foo f;
    f.name = ...;
    f.someValue = ...;
    f.someStuff = ...;
    if (everythingIsOk)
    {
        //TODO:
        //Delete the old object pointed to by currentFooSetting (if it's not pointed to by any other shared_ptr, of course)
        //Allocate some new memory to put f into... or maybe reuse *currentFooSetting if it's now free idc.
        //Copy f to the new memory location
        //
    }
}

如果一切正常,我想将 f 移到堆上并让 currentFooSetting 指向它。 我该怎么做?

看来我可以这样做:(

std::shared_ptr<Foo> newFooSetting = std::make_shared<Foo>();
*newFooSetting = f;
currentFooSetting = newFooSetting;

使用局部变量更好地强调分配、复制和替换之间的分离。) 但即使读完 https://en.cppreference.com/w/cpp/memory /shared_ptrhttps://en.cppreference.com/w/cpp/memory/shared_ptr/make_shared 我不知道这是否是这样做的“方式”。

Please note that with the words "object" and "move" in the title, I do not mean the C++-specific concepts of what an object is and what it means to move an object.

I have a local variable of a pretty simple struct type where I accumulate some values read from a config file.

struct Foo
{
    std::string name;
    float someValue;
    int someStuff;
};

// This stores the current settings
std::shared_ptr<Foo> currentFooSetting;

void readSettings()
{
    Foo f;
    f.name = ...;
    f.someValue = ...;
    f.someStuff = ...;
    if (everythingIsOk)
    {
        //TODO:
        //Delete the old object pointed to by currentFooSetting (if it's not pointed to by any other shared_ptr, of course)
        //Allocate some new memory to put f into... or maybe reuse *currentFooSetting if it's now free idc.
        //Copy f to the new memory location
        //
    }
}

If everything is OK, I want to move f onto the heap and have currentFooSetting point to that.
How do I do that?

It seems I could do this:

std::shared_ptr<Foo> newFooSetting = std::make_shared<Foo>();
*newFooSetting = f;
currentFooSetting = newFooSetting;

(Using a local variable to better emphasize the separation between the allocation, copying, and replacing.)
But even after reading through https://en.cppreference.com/w/cpp/memory/shared_ptr and https://en.cppreference.com/w/cpp/memory/shared_ptr/make_shared I have no idea whether that's "the way" of doing this.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

友谊不毕业 2025-01-21 04:09:01

这种方式如何

if (currentFooSetting) {
    *currentFooSetting = f;
} else {
    currentFooSetting = std::make_shared<Foo>(f);
}

确保您只有一个共享指针,并且一旦创建它,​​它的值就会在更新时更改。或者,如果现有共享指针持有者应保留其值,只需分配一个新值:

currentFooSetting = std::make_shared<Foo>(f);

这将“分叉”当前设置的视图——共享指针持有者将旧值保留为旧值,但新共享指针的函数获得新值。

哪个更有意义取决于您的设计(这是 Ted Lyngmo 在评论中提出的问题)。两个代码片段都假设您的 Foo 类具有合适的(复制)构造函数。

How about

if (currentFooSetting) {
    *currentFooSetting = f;
} else {
    currentFooSetting = std::make_shared<Foo>(f);
}

this sort-of ensures that you have just one shared pointer, and once it is created, its value is changed on update. Alternately, if existing holders-of-the-shared-pointer should keep their values, just assign a new one:

currentFooSetting = std::make_shared<Foo>(f);

This will "fork" the views of current settings -- holders-of-a-shared-pointer keep the old one with old values, but functions that newly share the pointer get the new value.

Which makes more sense depends on your design (which is what Ted Lyngmo asks in a comment). Both code snippets assume your Foo class has suitable (copy) constructors.

孤寂小茶 2025-01-21 04:09:01

它可以比问题中的尝试更简单:

if (everythingIsOk) {
    currentFooSetting = std::make_shared<Foo>(std::move(f));
}

std::make_shared 将分配动态内存,并且新对象将通过从 f 移动来初始化。我们也可以复制,但在这种情况下,本地 f 即将超出范围,因此可以安全地从中移动。

分配currentFooSetting将导致它销毁先前指向的对象(如果有,并且没有其他所有者),并且currentFooSetting成为新创建的对象的所有者。

It can be done more simply than the attempt in the question:

if (everythingIsOk) {
    currentFooSetting = std::make_shared<Foo>(std::move(f));
}

std::make_shared will allocate dynamic memory and the new object will be initialised by move from f. We could copy too, but in this case the local f is about to go out of scope, so it is safe to move from it.

Assigning currentFooSetting will cause it to destroy the previously pointed object (if any, and if there are no other owners), and currentFooSetting becomes the owner of the newly created object.

盛装女皇 2025-01-21 04:09:01

这是一个 readSettings 函数模板,支持移动分配给现有 Foo 或无条件移动构造新的 Foo(如果 everythingIsOk > is true):

template<bool Reassign = true>
void readSettings() {
    Foo f;
    
    // ...

    if (everythingIsOk) {
        if constexpr (Reassign) {
            // move assign if you've already createad a shared Foo
            if(currentFooSetting) *currentFooSetting = std::move(f);
            // or move construct a new Foo
            else currentFooSetting = std::make_shared<Foo>(std::move(f));
        } else {
            // always move construct a new Foo
            currentFooSetting = std::make_shared<Foo>(std::move(f));
        }
    }
}

然后使用 readSettings()/readSettings() 将分配移动到现有的FooreadSettings() 始终移动构造一个新的 Foo

Here's a readSettings function template supporting both move assigning to an existing Foo or unconditionally move constructing a new Foo (if everythingIsOk is true):

template<bool Reassign = true>
void readSettings() {
    Foo f;
    
    // ...

    if (everythingIsOk) {
        if constexpr (Reassign) {
            // move assign if you've already createad a shared Foo
            if(currentFooSetting) *currentFooSetting = std::move(f);
            // or move construct a new Foo
            else currentFooSetting = std::make_shared<Foo>(std::move(f));
        } else {
            // always move construct a new Foo
            currentFooSetting = std::make_shared<Foo>(std::move(f));
        }
    }
}

Then either use readSettings()/readSettings<true>() to move assign to an existing Foo or readSettings<false>() to always move construct a new Foo.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文