创建 shared_ptr 来堆叠对象
Create shared_ptr to stack object
在我的方法中,Player 对象的创建方式如下:
Player player(fullName,age);
我的老师给了我们一段带有构造函数的代码,该构造函数将 shared_ptr 传递给玩家对象。
//constructor of the class
SomeClass(const std::shared_ptr<Socket> client, std::shared_ptr<Player> player)
假设我们要调用 SomeClass 的构造函数并传递我们在堆栈上创建的播放器对象。
是否曾经safe/possible/good从堆栈对象创建shared_ptr?
为了让问题更容易理解,假设我们有两个大代码项目,我们想合并它们,所以一个项目的方法被另一个项目调用,我们是否应该重写所有文件以使用 shared_ptr或 stack objects exclusivly(对于需要连接的方法)或者我们应该只创建一个 shared_ptr 到 stack object.
为什么我不确定结果:
如果创建堆栈对象的范围结束但 shared_ptr 仍在使用,反之亦然。
stackobject 在超出范围时被删除,还是因为仍然存在对该对象的引用而保持活动状态(尽管在另一个 class 中)?
shared_ptr 超出范围并尝试删除该对象,即使堆栈对象正在引用它也可以吗?
注意:我知道我可以使用以下内容并传递播放器
shared_ptr<Player> player{ new Player {fullName,age} };
创建指向堆栈对象的共享指针是不安全的,因为堆栈对象一旦包含函数 returns 就会被销毁。本地对象是隐式自动分配和释放的,试图干预肯定会调用多种未定义的行为。
Is it ever safe/possible/good to create a smart_ptr from a stack object?
安全?仅当您可以保证创建该对象的堆栈只会在所有shared_ptr
伪拥有它之后才结束。
可能?当然:向 shared_ptr
的构造函数传递一个什么都不做的删除器对象:
auto sptr = shared_ptr<Player>(&player, [](Player *) {});
当最后一个shared_ptr
被销毁时,将调用删除器,不会删除任何内容。
好?并不真地。如上所述,在此类代码中无法普遍保证安全。根据您的代码结构,这可能是合法的。但这需要非常小心。
此 SomeClass
期望声明对资源的所有权;这就是为什么它需要 shared_ptr
。通过向它传递一个并不真正拥有它引用的对象的 shared_ptr
,你有点在撒谎。这意味着您和您的代码结构有责任不违反您对 SomeClass
做出的承诺,即它将共享控制该对象的生命周期。
共享指针的目的是管理动态创建对象的生命周期。只要有指向某个对象的共享指针存在,该对象就一定存在;当指向一个对象的最后一个共享指针被销毁时,该对象也被销毁。
堆栈对象具有根本不同的生命周期:它们一直存在,直到代码从创建它们的范围退出,然后它们被销毁。
生命周期的两个概念不兼容:共享指针无法确保超出范围的堆栈对象仍然存在。
所以不要将两者混为一谈。
安全是一个强词。
但是,您可以通过定义 StackObjectSharedPtr 来使代码更安全,强制 shared_ptr 实例化类型包含 "special" StackObjectDeleter
using PlayerStackSP = std::shared_ptr <Player, StackObjectDeleter> ;
class StackObjectDeleter {
public:
void operator () (void*) const {}
};
Player player(fullName,age);
std::shared_ptr<PlayerStackSP, StackObjectDeleter> player(&player, StackObjectDeleter());
StackObjectDeleter 将 default_delete 替换为删除器对象。 default_delete 只是调用 delete(或 delete [])。对于 StackObjectDeleter,什么也不会发生。
这是@Nicol Bolas 回答的更进一步。
Is it ever safe/possible/good to create a shared_ptr from a stack object?
我同意@Nicolas Bolas 的观点,它不安全。但是从堆栈对象
的 copy 创建 shared_ptr 可能是安全的
shared_ptr<Player> playerPtr(new Player(player));
当然,如果播放器是可复制的。
使用移动语义创建 shared_ptr
std::shared_ptr<Player> player_shared_ptr{ std::make_shared(std::move(player)) };
这样就避免了复制。您可能需要在相关 类 上实现移动构造函数才能使这种方法起作用。 Most/all std
对象支持开箱即用的移动语义(例如 string
、vector
等)
在我的方法中,Player 对象的创建方式如下:
Player player(fullName,age);
我的老师给了我们一段带有构造函数的代码,该构造函数将 shared_ptr 传递给玩家对象。
//constructor of the class
SomeClass(const std::shared_ptr<Socket> client, std::shared_ptr<Player> player)
假设我们要调用 SomeClass 的构造函数并传递我们在堆栈上创建的播放器对象。
是否曾经safe/possible/good从堆栈对象创建shared_ptr?
为了让问题更容易理解,假设我们有两个大代码项目,我们想合并它们,所以一个项目的方法被另一个项目调用,我们是否应该重写所有文件以使用 shared_ptr或 stack objects exclusivly(对于需要连接的方法)或者我们应该只创建一个 shared_ptr 到 stack object.
为什么我不确定结果:
如果创建堆栈对象的范围结束但 shared_ptr 仍在使用,反之亦然。
stackobject 在超出范围时被删除,还是因为仍然存在对该对象的引用而保持活动状态(尽管在另一个 class 中)?
shared_ptr 超出范围并尝试删除该对象,即使堆栈对象正在引用它也可以吗?
注意:我知道我可以使用以下内容并传递播放器
shared_ptr<Player> player{ new Player {fullName,age} };
创建指向堆栈对象的共享指针是不安全的,因为堆栈对象一旦包含函数 returns 就会被销毁。本地对象是隐式自动分配和释放的,试图干预肯定会调用多种未定义的行为。
Is it ever safe/possible/good to create a smart_ptr from a stack object?
安全?仅当您可以保证创建该对象的堆栈只会在所有shared_ptr
伪拥有它之后才结束。
可能?当然:向 shared_ptr
的构造函数传递一个什么都不做的删除器对象:
auto sptr = shared_ptr<Player>(&player, [](Player *) {});
当最后一个shared_ptr
被销毁时,将调用删除器,不会删除任何内容。
好?并不真地。如上所述,在此类代码中无法普遍保证安全。根据您的代码结构,这可能是合法的。但这需要非常小心。
此 SomeClass
期望声明对资源的所有权;这就是为什么它需要 shared_ptr
。通过向它传递一个并不真正拥有它引用的对象的 shared_ptr
,你有点在撒谎。这意味着您和您的代码结构有责任不违反您对 SomeClass
做出的承诺,即它将共享控制该对象的生命周期。
共享指针的目的是管理动态创建对象的生命周期。只要有指向某个对象的共享指针存在,该对象就一定存在;当指向一个对象的最后一个共享指针被销毁时,该对象也被销毁。
堆栈对象具有根本不同的生命周期:它们一直存在,直到代码从创建它们的范围退出,然后它们被销毁。
生命周期的两个概念不兼容:共享指针无法确保超出范围的堆栈对象仍然存在。
所以不要将两者混为一谈。
安全是一个强词。 但是,您可以通过定义 StackObjectSharedPtr 来使代码更安全,强制 shared_ptr 实例化类型包含 "special" StackObjectDeleter
using PlayerStackSP = std::shared_ptr <Player, StackObjectDeleter> ;
class StackObjectDeleter {
public:
void operator () (void*) const {}
};
Player player(fullName,age);
std::shared_ptr<PlayerStackSP, StackObjectDeleter> player(&player, StackObjectDeleter());
StackObjectDeleter 将 default_delete 替换为删除器对象。 default_delete 只是调用 delete(或 delete [])。对于 StackObjectDeleter,什么也不会发生。
这是@Nicol Bolas 回答的更进一步。
Is it ever safe/possible/good to create a shared_ptr from a stack object?
我同意@Nicolas Bolas 的观点,它不安全。但是从堆栈对象
的 copy 创建 shared_ptr 可能是安全的shared_ptr<Player> playerPtr(new Player(player));
当然,如果播放器是可复制的。
使用移动语义创建 shared_ptr
std::shared_ptr<Player> player_shared_ptr{ std::make_shared(std::move(player)) };
这样就避免了复制。您可能需要在相关 类 上实现移动构造函数才能使这种方法起作用。 Most/all std
对象支持开箱即用的移动语义(例如 string
、vector
等)