c++ - 是否可以将智能指针的内存重用于另一个对象?
问题描述
假设我有两种大小完全相同的不相关类型。
struct Foo { ... };
struct Bar { ... };
现在,假设我有一棵树Foo
,我想将其转换为Bar
.
template <typename Leaf>
struct Tree
{
Leaf data;
std::unique_ptr<Tree> lhs;
std::unique_ptr<Tree> rhs;
};
Tree<Foo> footree = ...;
Tree<Bar> bartree = convert(std::move(footree)); // <--
如何在重用堆分配的内存时执行此转换footree
?换句话说,我如何(安全地)将 a 转换Tree<Foo>
为 aTree<Bar>
而没有额外的内存分配?
这是我实际尝试做的一个简化示例。实际上Foo
,并且Bar
是具有不同数量的替代类型的递归变体。
解决方案
对于原始指针,这并不难。只需手动触发析构函数Foo
并通过放置 new 手动应用构造函数。这enable_if
是确保大小和对齐匹配的 SFINAE。
#include <iostream>
#include <vector>
template<typename U, typename V, typename... Args,
std::enable_if_t<sizeof(U) == sizeof(V) && alignof(U) == alignof(V), int> = 0>
U* repurpose_raw_ptr(V* ptr, Args&&... args)
{
ptr->~V();
return new ((void*)ptr) U(std::forward<Args>(args)...);
}
int main()
{
std::vector<int>* X = new std::vector<int>({1,2,3,4,5});
std::vector<double>* Y =
repurpose_raw_ptr<std::vector<double>>(X,
std::initializer_list<double>{1.,2.,3.,4.,5.});
std::cout << Y->at(0) << " " << Y->at(4);
delete Y;
return 0;
}
您可以使用释放对象所有权的唯一指针方法将该函数应用于“转换” from std::unique_ptr<Foo>
to 。就像是:std::unique_ptr<Bar>
release()
std::unique_ptr<Bar> X = ...;
std::unique_ptr<Foo> Y = std::unique_ptr<Foo>(repurpose_raw_ptr<Bar>(X.release(),...));
在这里,它假设delete Foo
并且delete Bar
与破坏原始指针的 Foo/Bar + dealloc 相同,我相信这可能并不总是如此。
一般来说,我不建议这样做,因为很难确保结构在跨平台环境中具有相同的大小/对齐方式。
编辑:以前,错过了您想以某种方式转换Foo
的Bar
内容。您必须临时将实例复制/移动Foo
到其他地方,然后触发内存重新利用。
推荐阅读
- reactjs - Firebase push() 函数抛出 .child() 不是函数错误
- python - 如何防止在Django中的每个测试用例之后刷新测试数据库中的数据
- c# - 如何使用 System.CodeDom 获取条件语句?: 不是 if-else 块
- docker - 如何使用运行 pm2 的 nodejs 为 docker 设置 pm2-logrotate?
- amazon-web-services - 如何将现有堆栈转换为嵌套堆栈
- cmake - Poco 项目的 CMake 构建中缺少 libcrypto.lib
- python - discord.ext.commands.errors.CommandInvokeError:命令引发异常:AttributeError:'Command'对象没有属性'strftime'
- r - 在 R 中绘制互惠尺度
- r - Parse 无法评估文本
- java - 我的客户数据在添加到我的列表时被截断