Я экспериментировал с shared_ptr
и make_shared
из C ++ 11 и запрограммировал небольшой игрушечный пример, чтобы увидеть, что на самом деле происходит при вызове make_shared
. В качестве инфраструктуры я использовал llvm / clang 3.0 вместе с библиотекой llvm std c ++ в XCode4.
class Object
{
public:
Object(const string& str)
{
cout << "Constructor " << str << endl;
}
Object()
{
cout << "Default constructor" << endl;
}
~Object()
{
cout << "Destructor" << endl;
}
Object(const Object& rhs)
{
cout << "Copy constructor..." << endl;
}
};
void make_shared_example()
{
cout << "Create smart_ptr using make_shared..." << endl;
auto ptr_res1 = make_shared
Теперь взгляните на результат, пожалуйста:
Создайте smart_ptr, используя make_shared ...
Конструктор make_shared
Конструктор копирования ...
Конструктор копирования ...
Деструктор
Деструктор
Создайте smart_ptr, используя make_shared: done.
Создайте smart_ptr, используя new ...
Конструктор new
Создайте smart_ptr, используя new: done.
Деструктор
Деструктор
Похоже, что make_shared
вызывает конструктор копирования два раза. Если я выделяю память для объекта
, используя обычный новый
, этого не происходит, создается только один объект
.
Меня интересует следующее. Я слышал, что make_shared
должен быть более эффективным, чем использование new
( 1 , 2 ) . Одна из причин заключается в том, что make_shared
выделяет счетчик ссылок вместе с объектом, которым нужно управлять, в том же блоке памяти. Хорошо, я понял.Это, конечно, более эффективно, чем две отдельные операции распределения.
Напротив, я не понимаю, почему это связано с затратами двух вызовов конструктора копирования Object
. Из-за этого я не уверен, что make_shared
более эффективен, чем распределение с использованием new
в в каждом случае. Я здесь не прав? Хорошо, хорошо, можно было бы реализовать конструктор перемещения для объекта
, но все же я не уверен, что это более эффективно, чем просто размещение объекта
через new
. По крайней мере, не во всех случаях. Было бы верно, если бы копирование объекта
было бы дешевле, чем выделение памяти для счетчика ссылок. Но внутренний счетчик ссылок shared_ptr
может быть реализован с использованием пары примитивных типов данных, верно?
Можете ли вы помочь и объяснить, почему make_shared
- это способ пойти с точки зрения эффективность, несмотря на указанные накладные расходы на копирование?