Что такое пустые указатели для в C++?

Мой вопрос прост: Что такое пустые указатели для в C++? (Те вещи Вы объявляете с void* myptr;)

Каково их использование? Я могу заставить их указать на переменную какого-либо типа?

20
задан Dr. Acula 18 May 2010 в 19:55
поделиться

13 ответов

void ptr - это, по сути, пустое поле. Заполните его чем хотите, но убедитесь, что вы пометили его (преобразование)

0
ответ дан 29 November 2019 в 23:27
поделиться

То, что вы могли бы делать на C с помощью void, но не может в C ++:

void * автоматически преобразуются в другие типы указателей. (Вы знаете , что это void * - вы не получаете никакой безопасности типа от принудительного явного приведения)

Struct* p = malloc( sizeof(Struct) );
// vs C++
Struct* p = (Struct*)malloc( sizeof(Struct) );
// Some will argue that that cast style is deprecated too, and c++ programmers 
// need to actually do this:
Struct* p = reinterpret_cast<Struct*>malloc( sizeof(Struct) );
// See what C++ did there? By making you write Struct a 3rd time, you can now be sure
// you know what you are doing!

void * также выполнял подсчет косвенных ссылок в C, обеспечивая большую безопасность при передаче указателей на функции, которые принимают указатель на указатель.

void funcInitializingOutPtr( void** ppOut)
{
  *ppOut = malloc( x );
}

int* out = NULL;
funcInitializingPtr(out);  // C would signal this as an error
funcInitializingPtr(&out); // correct
// vs C++ 
funcInitializingPtr( (void**)&out ); // so much safer needing that exlicit cast.
funcInitializingPtr( (void**)out);   // oops. thanks C++ for hiding the common error
0
ответ дан 29 November 2019 в 23:27
поделиться

По сути, это пережиток C.

Каково их применение?

В C они широко использовались и используются, но в C++, я думаю, они нужны очень редко, если вообще нужны, поскольку у нас есть полиморфизм, шаблоны и т.д., которые обеспечивают гораздо более чистый и безопасный способ решения тех же проблем, где в C использовались бы указатели void.

Могу ли я сделать так, чтобы они указывали на переменную любого типа?

Да. Однако, как отмечали другие, вы не можете использовать указатель void напрямую - сначала вы должны привести его к указателю на конкретный тип данных.

20
ответ дан 29 November 2019 в 23:27
поделиться

Да, это конструкция C (не специфичная для C ++), которая позволяет объявлять переменную-указатель, указывающую на любой тип. С таким указателем ничего нельзя сделать, кроме как вернуть его к реальному объекту, на который он фактически указывает. В современном C ++ void * в значительной степени вышел из моды, уступая во многих случаях общему коду на основе шаблонов.

7
ответ дан 29 November 2019 в 23:27
поделиться

От cplusplus.com:

Тип указателя void является специальным тип указателя. В C++, void представляет собой отсутствие типа, поэтому указатели void - это указатели, которые указывают на значение, которое не имеет типа (и, следовательно. также неопределенную длину и неопределенная длина и неопределенные свойства разыменования).

Это позволяет указателям пустоты указывать на любой тип данных, от целочисленного значения или поплавка до строки символов. Но взамен они имеют большое ограничение: данные, на которые они указывают не могут быть непосредственно разыменованы (что логично, поскольку у нас нет типа для разыменовывать), и по этой причине нам всегда придется приводить адрес в указателе void к некоторому другой тип указателя, который указывает на конкретный тип данных, прежде чем разыменовывать его.

4
ответ дан 29 November 2019 в 23:27
поделиться

Однажды они в C выполнили задание быть указателем на что угодно, указателем, который вы передали библиотекам, а они вернули вам как пользовательские данные. Пустота * вообще бесполезна без того, чтобы программист каким-либо образом знал их контекст, поскольку вы не знаете, что находится на другом конце, вы ничего не можете сделать с данными. За исключением того, что передайте указатель на другой код, который знает.

Я не понимаю, почему люди не использовали просто неопределенные типы, то есть непрозрачные указатели. Типовая безопасность, пользовательские данные.

В современном C ++ указатель на пустоту почти полностью заменен полиморфизмом и генерируемым шаблоном универсальным кодом. Однако вам все равно, возможно, придется использовать их для взаимодействия с собственным кодом C. Чтобы безопасно использовать void * в любом данном контексте, приводите только один тип к void *. Таким образом, вы точно знаете, на что он указывает. Если вам нужно больше типов, вы можете быстро создать
struct safevoidptr { base * ptr };
или
struct safevoidptr {void * ptr; тип int; };
Я считаю, что dynamic_cast также может преобразовывать void * в полиморфные типы, хотя я никогда не использовал dynamic_cast, поэтому не верьте мне на слово.

3
ответ дан 29 November 2019 в 23:27
поделиться

Указатель на void является наиболее близкой концепцией к указателю языка ассемблера. Это общий указатель, который резервирует место для адреса или местоположения чего-либо (функции или данных). Как заявляли другие, он должен быть приведен, прежде чем его можно будет разыменовать.

Указатель void - популярный инструмент для представления концепций объектно-ориентированного программирования на языке C. Одна проблема с указателем void заключается в том, что содержимое может не соответствовать восприятию получателя. Если вызывающий устанавливает указатель так, чтобы он указывал на квадрат, но принимающая функция ожидает указатель на кота, с приведением указателя будут происходить неопределенные и странные вещи.

1
ответ дан 29 November 2019 в 23:27
поделиться

Поскольку существует уже так много хороших ответов, я бы просто предоставил один из наиболее распространенных, которые я видел: специализация шаблонов. Если я не помню ошибочно, в книге Страуструпа есть пример этого: специализация вектора как вектора, а затем получение вектора (частным образом) из вектора. Таким образом, вектор будет содержать только простые, легко встроенные коды (т.е. вызов соответствующих функций из вектора). Это уменьшит количество дублирований, когда вектор компилируется в программе, которая использует его с множеством разных типов указателей.

1
ответ дан 29 November 2019 в 23:27
поделиться

Я использую их в своих динамических списках для хранения большего количества типов объектов (все они являются указателями).
typedef void* Object; Затем, когда вы объявляете переменную Object, вы можете хранить в ней любой указатель. Это более или менее полезно в зависимости от потребностей.
Я нахожу его очень полезным, когда вам нужно где-то хранить указатель, и вы не можете просто вывести все ваши классы из одного. В остальных случаях, как сказали другие, лучше использовать шаблоны, полиморфизм и т.д.

0
ответ дан 29 November 2019 в 23:27
поделиться

Примерно одним из немногих вариантов использования указателей void в C ++ является их использование для перегрузки операторов new . Все операторы new по определению возвращают тип void * . В остальном то, что говорили другие, правда.

6
ответ дан 29 November 2019 в 23:27
поделиться

Я полагаю, что void * - это место в памяти, где вы можете привести / сохранить что угодно. Некоторые эксперты по языку не согласятся со мной в этом вопросе. но я успешно использовал его во многих своих проектах.

Единственная проблема, которую я вижу, - это безопасность типов

0
ответ дан 29 November 2019 в 23:27
поделиться

Указатель void может указывать на что угодно, если только его память: -)

Стандарт C утверждает, что вы можете преобразовать любой указатель в указатель void, а затем вернуть его обратно без потерять что-нибудь.

1
ответ дан 29 November 2019 в 23:27
поделиться

Скрытие типа. Он все еще имеет свое допустимое применение в современном C ++. Покопайтесь в исходном коде в ускоренном темпе, и вы найдете несколько. Как правило, использование пустоты * зарыто очень глубоко в недрах более сложной конструкции, которая обеспечивает безопасность типов интерфейса при выполнении черной и злой магии внутри.

4
ответ дан 29 November 2019 в 23:27
поделиться
Другие вопросы по тегам:

Похожие вопросы: