В программировании на C++ мне часто нужно получить адрес указателя и преобразовать его в void **
. Например, обычно при использовании CUDA:
int main() {
float *data;
size_t size = sizeof(float) * 1024;
CUDA_CHECK(cudaMalloc((void **)&data, size)); // question about this line
...
CUDA_CHECK(cudaFree(static_cast<void *>(data)));
return 0;
}
Моя проблема в том, что преобразование float **
в void **
с использованием преобразования типов в стиле C меня раздражает, поскольку я не хочу использовать это в программировании на C++.
До сих пор я использовал reinterpret_cast<void **>(&data)
, но меня это не устраивает. По какой-то причине я не думаю, что это правильный способ сделать это.
Однажды я очень глупо пытался сделать &static_cast<void *>(data)
, так как это явно не удается получить адрес из rvalue.
Я выполнил поиск в Google и Stack Overflow, но мне трудно найти подходящие ключевые слова для запроса.
Я также изучал концепцию ссылки rvalue, но я не думаю, что она была разработана для этой проблемы.
Итак, мой вопрос: каков правильный способ C++ для преобразования из float **
в void **
в этом контексте? Кроме того, есть ли способ перейти от static_cast
к void *
и по-прежнему получить адрес из возвращенного значения, например ссылку rvalue? (PS: я все еще не совсем понимаю ссылку на rvalue, так что простите меня, если это ошибка новичка)
Редактировать --------------
Извините, я не ясно выразился. Я не хочу здесь объявлять void *
. Я просто хочу каким-то образом выполнить «правильное» приведение C++, желательно в одной строке.
Больше Редактировать ----------
Я понимаю, что правильно использовать void *
, как @ M.M указал ниже (на самом деле, это именно то, чем я занимаюсь в течение некоторого времени). Мне просто любопытно, есть ли какой-нибудь правильный способ избежать использования void *
.
Почему эта библиотека принимает параметры void **
, тогда как void *
подойдет?
@SidS • похоже, что это эквивалент C API параметра void*&
в C++.
@SidS это параметр «out», функция «возвращает» значение void *
и использует значение, возвращаемое функцией, для кодов ошибок.
Я бы сделал так:
void *newdata;
CUDA_CHECK(cudaMalloc(&newdata, size));
float *data = static_cast<float *>(newdata);
CUDA_CHECK(cudaFree(data)); // or pass newdata, doesn't matter
И, очевидно, я бы превратил эти фрагменты в интеллектуальный указатель с помощью RAII.
Извините, я не разъяснил это в OP. Я знаю, что это хороший способ сделать это. Но что, если я не хочу использовать указатель void *
? Мне интересно, есть ли способ избежать этого. Редактируем OP сейчас ...
@TerryTsao Этот ответ показывает правильный путь. Версия с reinterpret_cast
(которая в точности эквивалентна приведению в стиле C) имеет неопределенное поведение, которое «должно работать», похоже, ваши паучьи чувства действительно говорят вам, что не стоит полагаться на работу UB.
@ M.M Спасибо за ваш комментарий. Я думал о том же самом.
Использование
reinterpret_cast<void**>(&data)
является - это "правильный" способ заброса здесь.