Когда вы объявляете переменную как auto
для ее типа, ее фактический тип определяется из любого значения, присвоенного переменной во время ее инициализации.
Тип pstr
выводится как unique_ptr<string>
, потому что это то, что make_unique<string>(5, '*')
возвращает.
auto pstr2(pstr.release());
не делает то, что вы думаете, что оно делает. release()
не возвращает unique_ptr<string>
, как вы ожидаете. Он возвращает необработанный указатель string*
, который удерживался pstr
. Таким образом, тип pstr2
выводится как string*
, а не как unique_ptr<string>
(а поскольку pstr
отказался от владения указателем string*
, вам нужно явно вызвать delete pstr2;
, когда вы закончите или же объект string
будет пропущен).
Аналогично auto pstr3(move(pstr2));
. Поскольку pstr2
является необработанным string*
, а std::move()
является просто копией необработанного указателя, тип pstr3
также выводится как string*
, а не unique_ptr<string>
. pstr2
и pstr3
указывают на один и тот же объект string
в памяти, поэтому ни один из них не является нулевым, и оба выводят одинаковые данные на консоль.
Если вы измените тип pstr2
для явной замены auto
на unique_ptr<string>
(или decltype(pstr)
), тогда вы получите ожидаемое поведение, например:
auto pstr = make_unique<string>(5, '*');
cout << (pstr ? *pstr : "pstr is empty") << endl;
unique_ptr<string> pstr2(pstr.release());
// or: decltype(pstr) pstr2(pstr.release());
cout << (pstr ? *pstr : "pstr is empty") << endl;
cout << (pstr2 ? *pstr2 : "pstr2 is empty") << endl;
auto pstr3(move(pstr2));
// or: decltype(pstr2) pstr3(move(pstr2));
cout << (pstr2 ? *pstr2 : "pstr2 is empty") << endl;
cout << (pstr3 ? *pstr3 : "pstr3 is empty") << endl;
Output
*****
pstr is empty
*****
pstr2 is empty
*****
Демоверсия