将 object 从局部变量移动到 std::shared_ptr
Move object from local variable to std::shared_ptr
请注意,标题中的“object”和“移动”并不是指 C++ 特定的概念,即 object 是什么以及移动意味着什么一个 object.
我有一个非常简单的结构类型的局部变量,我在其中积累了一些从配置文件中读取的值。
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_ptr and https://en.cppreference.com/w/cpp/memory/shared_ptr/make_shared 我也不知道这是否是这样做的“方式”。
怎么样
if (currentFooSetting) {
*currentFooSetting = f;
} else {
currentFooSetting = std::make_shared<Foo>(f);
}
this sort-of 确保您只有一个共享指针,并且一旦它被创建,它的值就会在更新时改变。或者,如果现有 holders-of-the-shared-pointer 应该保留它们的值,只需分配一个新值:
currentFooSetting = std::make_shared<Foo>(f);
这将“分叉”当前设置的视图 -- holders-of-a-shared-pointer 旧值保留旧值,但新共享指针的函数获得新值。
哪个更有意义取决于您的设计(这是 Ted Lyngmo 在评论中提出的问题)。这两个代码片段都假定您的 Foo
class 具有合适的(复制)构造函数。
比问题中的尝试更简单:
if (everythingIsOk) {
currentFooSetting = std::make_shared<Foo>(std::move(f));
}
std::make_shared
将分配动态内存,新对象将通过从 f
移动来初始化。我们也可以复制,但在这种情况下,本地 f
即将超出范围,因此从中移动是安全的。
分配currentFooSetting
将导致它销毁先前指向的对象(如果有的话,并且如果没有其他所有者),并且currentFooSetting
成为新创建对象的所有者。
这是一个 readSettings
函数模板,支持移动分配给现有 Foo
或无条件移动构造新的 Foo
(如果 everythingIsOk
是 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<true>()
移动分配给现有的 Foo
或 readSettings<false>()
总是移动构造一个新的 Foo
.
请注意,标题中的“object”和“移动”并不是指 C++ 特定的概念,即 object 是什么以及移动意味着什么一个 object.
我有一个非常简单的结构类型的局部变量,我在其中积累了一些从配置文件中读取的值。
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_ptr and https://en.cppreference.com/w/cpp/memory/shared_ptr/make_shared 我也不知道这是否是这样做的“方式”。
怎么样
if (currentFooSetting) {
*currentFooSetting = f;
} else {
currentFooSetting = std::make_shared<Foo>(f);
}
this sort-of 确保您只有一个共享指针,并且一旦它被创建,它的值就会在更新时改变。或者,如果现有 holders-of-the-shared-pointer 应该保留它们的值,只需分配一个新值:
currentFooSetting = std::make_shared<Foo>(f);
这将“分叉”当前设置的视图 -- holders-of-a-shared-pointer 旧值保留旧值,但新共享指针的函数获得新值。
哪个更有意义取决于您的设计(这是 Ted Lyngmo 在评论中提出的问题)。这两个代码片段都假定您的 Foo
class 具有合适的(复制)构造函数。
比问题中的尝试更简单:
if (everythingIsOk) {
currentFooSetting = std::make_shared<Foo>(std::move(f));
}
std::make_shared
将分配动态内存,新对象将通过从 f
移动来初始化。我们也可以复制,但在这种情况下,本地 f
即将超出范围,因此从中移动是安全的。
分配currentFooSetting
将导致它销毁先前指向的对象(如果有的话,并且如果没有其他所有者),并且currentFooSetting
成为新创建对象的所有者。
这是一个 readSettings
函数模板,支持移动分配给现有 Foo
或无条件移动构造新的 Foo
(如果 everythingIsOk
是 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<true>()
移动分配给现有的 Foo
或 readSettings<false>()
总是移动构造一个新的 Foo
.