Вопросы по использованию умных указателей в структуре addrinfo в Winsock - PullRequest
0 голосов
/ 25 января 2019

Я пытаюсь обработать указатель addrinfo winsock с помощью unique_ptr.После некоторого исследования я нашел ответ, который не очень хорошо объяснили, так что теперь я в замешательстве.(Ответ, о котором я говорю: Умные указатели со структурой addrinfo )

Итак, мое общее понимание unique_ptr говорит, что синтаксис следующий: unique_ptr<type of handled data, type of function deleting the data>(pointer, deleter function pointer);.

Базовым примером этого будет:

void deleteInt(int* ptr){...}

int* ptr = new int;
unique_ptr(int, void(*)(int*)>(ptr, deleteInt);

Обратите внимание, что тип функции не определяет имя и просто имеет (*).

Теперь, наконец, на мой вопрос:В ответе, который я упоминал выше, код делает что-то странное.Вместо того, чтобы быть unique_ptr<addrinfo, void(*)(addrinfo*)>... это unique_ptr<addrinfo, void(__stdcall*)(addrinfo*)>..., и никто, кажется, не подвергает сомнению это.Как так?Как это меняет тип функции?Что такое __stdcall?Почему это даже работает, поскольку T (name*)() даже не имеет допустимого синтаксиса?Излишне говорить, что просто наличие void(*)(addrinfo*) в качестве типа функции не работает и выдает кучу непонятных ошибок шаблона, которые я не понимаю.

1 Ответ

0 голосов
/ 25 января 2019

__stdcall - это соглашение о вызовах , которое управляет передачей параметров функции, очисткой стека вызовов и т. Д. В вашем примере int* не указываетсясоглашение о вызовах для его удалителя, поэтому используется соглашение о вызовах по умолчанию компилятора (обычно __cdecl).Но функции API определили соглашения о вызовах для целей взаимодействия, поэтому вы должны использовать правильное соглашение.Почти все Win32 API (за редким исключением) используют соглашение о вызовах __stdcall.

Вместо того, чтобы жестко кодировать тип средства удаления, было бы проще использовать вместо него decltype и позволить компилятору определить тип дляВы:

addrinfo *addr;
getaddrinfo(..., &addr);
unique_ptr<addrinfo, decltype(&::freeaddrinfo)> addrPtr(addr, &::freeaddrinfo);
...