适用于 std::unique_ptr 的内存高效自定义删除器?
Memory-efficient custom deleter for std::unique_ptr?
这可能有点特定于实现,但其中一些似乎是基本的。
我确定我一定在标准库中缺少某些内容。
问题是这样的:
我想实现一个删除器为free()
的std::unique_ptr
[ 因为该值是通过malloc()
分配的 ]
当然,有很多关于如何做到这一点的选择,但是 (至少在 x86-64 的 G++ 4.8.4 中(它们似乎具有不同的内存使用含义。
例如: 方法一:
std::unique_ptr<char, std::function<void(void*)>> ptr_a(malloc(10), free);
然而sizeof(ptr_a)
== 40 字节(8 表示 void*,32 表示 std::function<>(
方法2:
std::unique_ptr<void, void (*)(void*)> ptr_b(malloc(10), free);
好一点,因为sizeof(ptr_b)
== 16 个字节(8 个表示 void*,8 个表示裸函数指针 ](
方法3:
template <void (*T)(void*)>
class Caller {
public:
void operator()(void* arg) {
return T(arg);
}
};
std::unique_ptr<void, Caller<free>> ptr_c(malloc(10));`
在这一点上,sizeof(ptr_c)
== 8 字节(可能的最小值( - 但我不得不引入一个几乎是纯样板的类(并且,如图所示,很容易模板化(。
这似乎是一个简单的模式 - STL 中是否有某些元素可以执行Caller<>
上面所做的操作?
当然,当在一个普通类型上调用 delete 时,默认情况下 g++ 确实显示为 free(( - 但这似乎远非标准所保证的(如果没有别的,可以从默认的分配/释放函数重新定义 new/delete,然后default_delete调用替换 delete(。
此外,在其他情况下,在纯 C 库中分配的某些对象的释放将通过简单的函数调用而不是删除器来实现。 为了使 std::unique_ptr 正确有效地调用它们,必须将此类分配/释放函数包装在类中似乎有些乏味 - 这让我认为我错过了一些东西(大多数其余的现代C++规范似乎都经过深思熟虑(。
C++11 有一个integral_constant
类型,适用于非整数类的东西。 在 C++14 中,有一个constexpr
转换回该值。
因此,在 C++14 中,我们可以做到:
std::unique_ptr<void, std::integral_constant<decltype(free)*, free>> ptr_c(malloc(10));
这很尴尬。 (这依赖于这样一个事实,即()
将在其左侧参数上考虑投射到函数指针(。
我们可以免费硬编码为:
using default_free = std::integral_constant<decltype(free)*, free>;
std::unique_ptr<void, default_free> ptr_c(malloc(10));
以消除使用现场的一些噪音。
在 C++17 中,我们可以编写一个助手:
template<auto t>
using val = std::integral_constant< std::decay_t<decltype(t)>, t >;
给我们:
std::unique_ptr<void, val<free>> ptr_c(malloc(10));
在我看来,这更干净。
活生生的例子。
我们可以在 C++11 中编写自己的版本:
template<class T, std::decay_t<T> t>
struct val {
constexpr operator T() noexcept const { return t; }
};
using default_free = val<decltype(free), free>;
std::unique_ptr<void, default_free> ptr_c(malloc(10));
还有使用无状态 lambda 的第 4 个选项:
auto free_lmbd = [](void *_ptr) { free (_ptr);};
std::unique_ptr<void, decltype (free_lmbd)> ptr {malloc(10), free_lmbd};
它也将有 8 个字节(至少在我的计算机上(,与您的第 3 个选项相同。
我建议阅读 http://www.bfilipek.com/2016/04/custom-deleters-for-c-smart-pointers.html
- C++映射:具有自定义类的运算符[]不起作用(总是返回0)
- 如何将点击的信号和插槽添加到qt中的自定义按钮中
- C++自定义比较函数
- 如何比较自定义类的std::变体
- std::设置自定义比较器
- 如何正确实现和访问运算符的各种自定义枚举器
- flutter:即使shouldRepaint()返回true,自定义画家也不会重新绘制
- 自定义先决条件对移动分配运算符有效吗
- 使用VS Code和CMake Tools运行自定义命令
- 如何创建从Maya(或类似程序)到虚幻引擎的自定义数据导出插件
- std::ranges::elements_view,用于自定义类似元组的数据
- 跟随整数索引列表的自定义类迭代器
- 参数化自定义CMake工具链
- 使用自定义比较函数使用std::sort()对矢量字符串进行排序时出现问题
- 如何在自定义类中启用'auto loops'?
- 使用QJsEngine在Qt中注册自定义类型
- Qt自定义QPush按钮未显示在布局上
- 适用于 std::unique_ptr 的内存高效自定义删除器?
- C++:用于高效插入和检索自定义数据的数据结构
- c++:使用自定义分配器时高效的swap()