(1) Конечно, лучше проверить реализацию, но вы все равно можете сделать некоторые проверки из вашей программы.
Блок управления выделяется динамически, поэтому для определения его размера вамможет перегрузить новый оператор.
Тогда вы также можете проверить, предоставляет ли std :: make_shared некоторую оптимизацию размера блока управления.В правильной реализации я ожидал бы, что это сделает два выделения (objectA и блок управления):
std::shared_ptr<A> i(new A());
Однако это сделает только одно выделение (и затем objectA инициализируется с размещением new):
auto a = std::make_shared<A>();
Рассмотрим следующий пример:
#include <iostream>
#include <memory>
void * operator new(size_t size)
{
std::cout << "Requested allocation: " << size << std::endl;
void * p = malloc(size);
return p;
}
class A {};
class B
{
int a[8];
};
int main()
{
std::cout << "Sizeof int: " << sizeof(int) << ", A(empty): " << sizeof(A) << ", B(8 ints): " << sizeof(B) << std::endl;
{
std::cout << "Just new:" << std::endl;
std::cout << "- int:" << std::endl;
std::shared_ptr<int> i(new int());
std::cout << "- A(empty):" << std::endl;
std::shared_ptr<A> a(new A());
std::cout << "- B(8 ints):" << std::endl;
std::shared_ptr<B> b(new B());
}
{
std::cout << "Make shared:" << std::endl;
std::cout << "- int:" << std::endl;
auto i = std::make_shared<int>();
std::cout << "- A(empty):" << std::endl;
auto a = std::make_shared<A>();
std::cout << "- B(8 ints):" << std::endl;
auto b = std::make_shared<B>();
}
}
Вывод, который я получил (конечно, это зависит от архитектуры и компилятора):
Sizeof int: 4, A(empty): 1, B(8 ints): 32
Just new:
- int:
Requested allocation: 4
Requested allocation: 24
Первое выделение для int - 4 байта,следующий для блока управления - 24 байта.
- A(empty):
Requested allocation: 1
Requested allocation: 24
- B(8 ints):
Requested allocation: 32
Requested allocation: 24
Смотрит, что блок управления (наиболее вероятно) 24 байта.
Вот почему использовать make_shared:
Make shared:
- int:
Requested allocation: 24
Только одно распределение, int + control block = 24 байта, меньше, чем раньше.
- A(empty):
Requested allocation: 24
- B(8 ints):
Requested allocation: 48
Здесь можно ожидать 56 (32 + 24), но, похоже, реализация оптимизирована.Если вы используете make_shared - указатель на фактический объект не требуется в блоке управления, а его размер составляет всего 16 байтов.
Другая возможность проверить размер блока управления:
std::cout<< sizeof(std::enable_shared_from_this<int>);
В моем случае:
16
Поэтому я бы сказал, что размер блока управления в моем случае составляет 16-24 байта, в зависимости от того, как он был создан.