3. Определим общие указатели, которые имеют корректные типы, чтобы указывать на переменные-члены name
age
экземпляра класса person
:int main()
{
shared_ptr
shared_ptr
4. Далее войдем в новую область видимости, создадим объект типа person
{
auto sperson (make_shared
5. Затем позволим первым двум общим указателям указывать на его члены name
age
. Прием, который мы задействуем, заключается в использовании конкретного конструктора типа shared_ptr
, который принимает общий указатель и указатель на член общего объекта. Таким образом можно управлять объектом, не указывая на него самого! shared_name = shared_ptr
shared_age = shared_ptr
}
6. После выхода из области видимости выведем на экран значения переменных name
age
. Это возможно только в том случае, если память для объекта все еще выделена. cout << "name: " << *shared_name
<< "\nage: " << *shared_age << '\n';
}
7. Компиляция и запуск программы дадут следующий результат. Из сообщения деструктора мы видим, что объект все еще жив и память для него выделена, когда мы получаем доступ к значениям переменных name
age
с помощью указателей на члены!$ ./shared_members
CTOR John Doe
name: John Doe
age: 30
DTOR John Doe
Как это работает
В этом разделе мы сначала создали общий указатель, управляющий объектом person, память для которого выделяется динамически. Затем создали два других умных указателя, указывающих на объект типа person
name
и age
.Чтобы подытожить созданный сценарий, взглянем на рис. 8.4.
Обратите внимание: shared_ptr1
person
, а shared_name
и shared_age
— на члены name
и age
того же объекта. По всей видимости, они будут управлять всем жизненным циклом объекта. Это возможно потому, что указатели внутреннего блока управления все еще ссылаются на тот же блок управления, независимо от того, на какой подобъект указывают отдельные общие указатели.В этом сценарии счетчик использования блока управления равен 3
shared_ptr1
, поскольку другие общие указатели все еще владеют объектом.При создании подобных экземпляров общих указателей, указывающих на члены общего объекта, синтаксис выглядит несколько странно. Чтобы получить экземпляр типа shared_ptr
name
общего экземпляра типа person
, нужно написать следующий код:auto sperson (make_shared
auto sname (shared_ptr
Чтобы получить указатель на конкретный член общего объекта, мы создаем экземпляр общего указателя, чей тип специализирован для того члена, к которому нужно получить доступ. Именно поэтому используем конструкцию shared_ptr<string
person
, а в качестве второго аргумента — адрес объекта, которым будет пользоваться новый общий указатель при разыменовании.Генерируем случайные числа и выбираем правильный генератор случайных чисел
Чтобы получить случайные числа, программисты С++ до появления С++11 обычно просто использовали функцию rand()
Эти генераторы не говорят сами за себя, так что в данном разделе рассмотрим их все. Мы увидим, чем они отличаются, научимся выбирать правильный и узнаем, что, скорее всего, никогда не будем ими пользоваться.
Как это делается
В этом примере мы реализуем процедуру, которая выводит на экран гистограмму, содержащую числа, создаваемые генератором случайных чисел. Затем запустим все генераторы случайных чисел, доступные в STL, и воспользуемся нашей процедурой, чтобы исследовать результаты. Данная программа содержит множество повторяющихся фрагментов, поэтому может быть полезным просто скопировать исходный код из репозитория, дополняющего эту книгу, а не писать повторяющийся код вручную.
1. Сначала включим все заголовочные файлы, а затем объявим об использовании пространства имен std
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;