C++ std::unique\u ptr的高效内存自定义删除程序?
这可能有点特定于实现,但其中一些似乎是基本的 我肯定我在标准图书馆里遗漏了什么 问题是: 我想实现一个C++ std::unique\u ptr的高效内存自定义删除程序?,c++,c++11,memory-management,stl,C++,C++11,Memory Management,Stl,这可能有点特定于实现,但其中一些似乎是基本的 我肯定我在标准图书馆里遗漏了什么 问题是: 我想实现一个std::unique\u ptr,其删除程序是free() [因为该值是通过malloc()]分配的] 当然,在如何做到这一点上有很多选择,但是 (至少在x86-64的g++4.8.4中)它们似乎具有不同的内存使用含义 例如: 方法1: std::unique_ptr<char, std::function<void(void*)>> ptr_a(malloc(10),
std::unique\u ptr
,其删除程序是free()
[因为该值是通过malloc()
]分配的]
当然,在如何做到这一点上有很多选择,但是
(至少在x86-64的g++4.8.4中)它们似乎具有不同的内存使用含义
例如:
方法1:
std::unique_ptr<char, std::function<void(void*)>> ptr_a(malloc(10), free);
稍微好一点,就像
sizeof(ptr_b)
==16字节(8表示空*,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));`
模板
类调用者{
公众:
void运算符()(void*arg){
返回T(arg);
}
};
std::unique_ptr ptr_c(malloc(10))`
此时,sizeof(ptr_c)
==8字节(可能的最小值)-但我必须介绍一个非常纯粹的样板类(如图所示,很容易模板化)
这似乎是一个如此简单的模式-STL中是否有某种元素可以像上面的调用者那样执行操作
当然,在对一个普通类型调用delete时,g++在默认情况下确实看起来是free(),但这似乎远没有得到标准的保证(如果没有其他保证,则可以从默认的分配/解除分配函数中重新定义new/delete,然后默认的_delete将调用替换delete)
此外,还有其他一些情况,在纯C库中分配的某些对象的释放将通过简单的函数调用而不是删除器来实现。在类中包装这样的分配/解除函数似乎是有点乏味的,以便得到STD::UnQuyJ-PTR正确和高效地调用它们——这使我认为我缺少了一些东西(大多数现代C++规范中的大部分似乎都是经过深思熟虑的)。.还有第四个选项可以使用无状态lambda:
auto free_lmbd = [](void *_ptr) { free (_ptr);};
std::unique_ptr<void, decltype (free_lmbd)> ptr {malloc(10), free_lmbd};
auto-free_-lmbd=[](void*_-ptr){free(_-ptr);};
std::unique_ptr ptr{malloc(10),free_lmbd};
它也将有8个字节(至少在我的电脑上),与您的第三个选项相同
我建议阅读C++11有一个integral\u常量
类型,它可以处理与整数不同的事物。在C++14中,有一个constexpr
转换回该值
因此,在C++14中,我们可以:
std::unique_ptr<void, std::integral_constant<decltype(free)*, free>> ptr_c(malloc(10));
在使用现场消除一些噪音
在C++17中,我们可以编写一个助手:
template<auto t>
using val = std::integral_constant< std::decay_t<decltype(t)>, t >;
模板
我们可以用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));
模板
结构值{
constexpr运算符T()noexcept const{return T;}
};
使用默认值_free=val;
std::unique_ptr ptr_c(malloc(10));
这个对象很难在编译单元之间传递而不违反ODR。哇,太酷了。我从来没有想过这样使用std::integral_constant
。@Quentin一个缺点是它不能与基于继承的重写一起工作。哇。疯子为了澄清这一点,我们的想法是,std::integral_constant
表示指向free
的函数指针的静态值,从而让我们将指向free
的指针作为析构函数,而不必花费指针大小的代价?如果这仍然增加了指针调用函数的成本,有什么意义吗?因此,如果不是free
它是一个内联函数,它会内联吗?我在上尝试过,看起来如果对内联函数使用integral\u constant
,它实际上会找到函数并内联它。如果它不是内联的(只是一个函数声明),那么它将使用call
调用它。很酷。
template<auto t>
using val = std::integral_constant< std::decay_t<decltype(t)>, t >;
std::unique_ptr<void, val<free>> ptr_c(malloc(10));
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));