如果我继续使用原始指针,在 shared_ptr 中包装指针是否保证它会被删除?
Does wrapping a pointer in shared_ptr guarantee it will be deleted if I continue to use the raw pointer?
我在 运行 时生成了一个散列 table,由全局变量填充。
inline A* global1 = new A();
inline A* global2 = new A();
inline A* global3 = new A();
std::map<A*, int> createMap() {
return std::map<A*, int>({{global1, 1}, {global2, 2}, {global3, 3}});
}
我想在 运行 期间向 map
添加新条目,这意味着我必须创建指向 A
.
的新指针
void doStuff(std::map<A*, int>& map) {
A* runTimeValue = new A();
map[runTimeValue] = 4;
}
然而,这会导致程序内存泄漏,因为当地图对象最终超出范围并被删除时,我将不得不担心删除 runTimeValue
。我考虑过将地图切换到 std::map<std::shared_ptr<A>, int>
,但使用 std::shared_ptr<A>
很困难,因为它有许多不同的子类。
我的一个解决方案是将 runTimeValue
包裹在 shared_ptr 中,以便它可以自动删除,然后继续使用原始指针。
void doStuff(std::map<A*, int>& map) {
A* runTimeValue = new A();
std::shared_ptr<A> temp(runTimeValue);
map[runTimeValue] = 4;
}
这行得通吗?在地图超出范围之前,我是否需要存储对 temp
的引用?有没有更好的方法来处理全局和 运行 时间指针的混合,其中必须删除 运行 时间指针但全局变量不需要?
编辑,正在使用的“程序”示例:
inline A* global1 = new A();
inline A* global2 = new A();
inline A* global3 = new A();
int main() {
while(true) {
std::map<A*, int> map = createMap();
doStuff(map);
doStuff(map);
doStuff(map);
}
}
不要那样做。
如果你使用智能指针,那么确保智能指针'owns'从一开始就是内存。 C++ 喜欢 RAII 概念。
我想你想要 unique_ptr
- https://en.cppreference.com/w/cpp/memory/unique_ptr
也就是智能点保证内存被删除
一般来说,总是使用智能指针而不是原始指针。这使所有权更加清晰。但是您可以在需要时将其作为原始指针 (*A) 公开。但是让智能指针清理一下。
你对此有点犹豫不决。你提出的建议不会有好结果。假设您实际上需要 指针映射...
如果地图对其中包含的对象拥有唯一所有权,请使用 std::map<std::unique_ptr <A>, int>
。如果它与代码的其他部分共享所有权,请使用 std::map<std::shared_ptr <A>, int>
.
然后,无论哪种方式:
对象不会意外消失,同时仍然存在于您的地图中
当您从地图中删除对象时,对象将被清理(或减少它们的引用计数)
对于您的全局对象,您可以根据需要使用 std::make_unique
或 std::make_shared
创建它们,而不是使用 new
。然后就可以像管理其他所有内容一样管理它们。
我在 运行 时生成了一个散列 table,由全局变量填充。
inline A* global1 = new A();
inline A* global2 = new A();
inline A* global3 = new A();
std::map<A*, int> createMap() {
return std::map<A*, int>({{global1, 1}, {global2, 2}, {global3, 3}});
}
我想在 运行 期间向 map
添加新条目,这意味着我必须创建指向 A
.
void doStuff(std::map<A*, int>& map) {
A* runTimeValue = new A();
map[runTimeValue] = 4;
}
然而,这会导致程序内存泄漏,因为当地图对象最终超出范围并被删除时,我将不得不担心删除 runTimeValue
。我考虑过将地图切换到 std::map<std::shared_ptr<A>, int>
,但使用 std::shared_ptr<A>
很困难,因为它有许多不同的子类。
我的一个解决方案是将 runTimeValue
包裹在 shared_ptr 中,以便它可以自动删除,然后继续使用原始指针。
void doStuff(std::map<A*, int>& map) {
A* runTimeValue = new A();
std::shared_ptr<A> temp(runTimeValue);
map[runTimeValue] = 4;
}
这行得通吗?在地图超出范围之前,我是否需要存储对 temp
的引用?有没有更好的方法来处理全局和 运行 时间指针的混合,其中必须删除 运行 时间指针但全局变量不需要?
编辑,正在使用的“程序”示例:
inline A* global1 = new A();
inline A* global2 = new A();
inline A* global3 = new A();
int main() {
while(true) {
std::map<A*, int> map = createMap();
doStuff(map);
doStuff(map);
doStuff(map);
}
}
不要那样做。
如果你使用智能指针,那么确保智能指针'owns'从一开始就是内存。 C++ 喜欢 RAII 概念。
我想你想要 unique_ptr
- https://en.cppreference.com/w/cpp/memory/unique_ptr
也就是智能点保证内存被删除
一般来说,总是使用智能指针而不是原始指针。这使所有权更加清晰。但是您可以在需要时将其作为原始指针 (*A) 公开。但是让智能指针清理一下。
你对此有点犹豫不决。你提出的建议不会有好结果。假设您实际上需要 指针映射...
如果地图对其中包含的对象拥有唯一所有权,请使用 std::map<std::unique_ptr <A>, int>
。如果它与代码的其他部分共享所有权,请使用 std::map<std::shared_ptr <A>, int>
.
然后,无论哪种方式:
对象不会意外消失,同时仍然存在于您的地图中
当您从地图中删除对象时,对象将被清理(或减少它们的引用计数)
对于您的全局对象,您可以根据需要使用 std::make_unique
或 std::make_shared
创建它们,而不是使用 new
。然后就可以像管理其他所有内容一样管理它们。