是说
使用std::make_shared
,因此如果使用特定于类的::new
设置了任何特殊行为,它将与operator new
不同。std::shared_ptr<T>(new T(args...))
因此,对于下面的类,如果我们使用
std::make_shared<MyClass>()
,那么 Tracker
无法观察到任何内容。
class MyClass
{
public:
static void operator delete(void * ptr, std::size_t sz)
{
Tracker::deallocated(sz);
::operator delete(ptr);
}
static void operator delete[](void * ptr, std::size_t sz)
{
Tracker::deallocated(sz);
::operator delete[](ptr);
}
static void * operator new(std::size_t sz)
{
Tracker::allocated(sz);
return ::operator new(sz);
}
static void * operator new[](std::size_t sz)
{
Tracker::allocated(sz);
return ::operator new[](sz);
}
}
但是,我也不想要定制的
::new
。所以我想知道我可以做什么来跟踪所有分配/解除分配的内存MyClass
。
正如@PepijnKramer 指出的,你最好使用
std::allocate_shared
而不是 std::make_shared
。它有助于区分不同的关注点。困难的部分是定义一个 tracking_allocator
模板类作为第一个参数传递给 std::allocate_shared
:
#include <memory>
#include <type_traits>
template<typename T>
struct tracking_allocator{
template<typename U>
struct rebind // this is a must for use with 'std::allocate_shared'
{ using other = struct tracking_allocator<U>; };
static T* allocate(std::size_t n){
static_assert(std::is_empty_v<tracking_allocator>, "allocator must be empty class");
return /*alloc and track 'n' elements of 'T'*/;
}; //! allocate(n);
static void deallocate(T* ptr, std::size_t n){
return /*dealloc and track 'n' elements of 'T' at starting at 'ptr'*/;
}; //! deallocate(ptr,n);
static void construct(T* ptr, auto&& ... args){
// do some tracking ...
std::construct_at(ptr, std::forward<Args>(args)...);
}; //! construct(ptr,args...);
static void destroy(T* ptr){
// do some tracking ...
std::destroy_at(ptr);
// do more tracking ...
}; //! destroy(ptr);
}; //! tracking_allocator<T>;
现在您可以使用
tracking_allocator
作为选择加入:
constexpr bool is_debug_mode = /*use std or tracking alloc*/;
using my_allocator = std::conditional_t<
is_debug_mode,
tracking_allocator<myclass>,
std::allocator<myclass>>;
auto myptr=std::allocate_shared<myclass>(my_allocator{});
您的跟踪逻辑现在完全独立于类定义,并且可以通过
is_debug_mode
打开和关闭。您还可以利用 std::allocate_shared
的分配器参数:
auto my_next_ptr=std::allocate_shared<myclass>(std::allocator<myclass>{});
但这不如主要方法灵活。因此,为了方便起见,您可以定义您选择的 make 函数:
auto make_myclass()
{ return std::allocate_shared(my_allocator{}); };
auto myptr = make_myclass();
您可以制作上述任何类和函数模板;但作为说明,这会让这篇文章变得过于复杂。