C ++ 17: Разница в хранении указателя между unique_ptr <char []> и shared_ptr <char []> - PullRequest
0 голосов
/ 06 июля 2018

Я путаюсь с:

unique_ptr<char[]> u_ptr = make_unique<char[]>(10);
sprint(u_ptr.get(), 10, "milos"); // get returns char*
cout << u_ptr.get(); // get returns char*

И

shared_ptr<char[]> s_ptr = make_shared<char[]>(10);
sprint(*s_ptr.get(), 10, "milos"); // get here returns char** ?
cout << *s_ptr.get(); // get here returns char** ?

Итак, в то время как unique_ptr<char[]> возвращает char* для базового массива, shared_ptr<char[]>, кажется, возвращает char(*)[] указатель на указатель массива? Я сделал несколько тестов, и я мог бы использовать shared_ptr<char> с удалением по умолчанию:

shared_ptr<char> s_ptr(new char[10], default_delete<char[]>());
sprint(s_ptr.get(), 10, "milos"); // get here returns char*, fine
cout << s_ptr.get(); // same here

Но я предполагаю, что идея C ++ 17 заключается не в подходе с shared_ptr<char>, а в специальном указателе удаления: default_delete<char[]>, потому что это было возможно до C ++ 17.

Может ли кто-нибудь уточнить правильное использование и почему происходит следующее:

unique_ptr<int> u = make_unique<int>(5);
auto iu = u.get(); // iu is typeof int*

одновременно

unique_ptr<int[]> ua = make_unique<int[]>(5);
auto iua = ua.get(); // iua is still typeof int* ?

Пока для shared_ptr:

shared_ptr<int> s = make_shared<int>(5);
auto is = s.get(); // is is typeof int*

но

shared_ptr<int[]> sa = make_shared<int[]>(5);
auto isa = sa.get(); // isa is typeof int** ???

.

1 Ответ

0 голосов
/ 06 июля 2018

std::unique_ptr имеет специальную специализацию для случая, когда T является типом массива. Это приводит к выбору правильного удаления по умолчанию.

К лучшему или худшему, std::shared_ptr нет (в то время как std::make_shared соответствует состоянию на c ++ 20).

Поведение, которое вы видите в shared_ptr, возвращающем T ** в результате вызова get (), является аномалией, которая была исправлена ​​в c ++ 17 (теперь она будет возвращать T *).

Это потому, что до c ++ 17 std::shared_ptr::element_type был T и std::shared_ptr::get возвращал T*.

Начиная с c ++ 17 element_type определяется как std::remove_extent_t<T>, а get() возвращает element_type*;

с учетом using SAI = std::shared_ptr<int[]>

в c ++ 14:

SAI::element_type = int[]

SAI::get() -> (int[])*, который распадается до int**

в c ++ 17:

SAI::element_type = int

SAI::get() -> int*

Ссылки на документацию для справки:

https://en.cppreference.com/w/cpp/memory/unique_ptr https://en.cppreference.com/w/cpp/memory/shared_ptr

Насколько мне известно, способ создания общего массива до c ++ 17 будет примерно таким:

#include <memory>

int main()
{
    auto uai = std::make_unique<int[]>(10);
    std::shared_ptr<int> sai { uai.release(), uai.get_deleter() };
}

и после с ++ 17:

#include <memory>

int main()
{
    std::shared_ptr<int[]> sai = std::make_unique<int[]>(10);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...