C ++ Void без указателя - PullRequest
       20

C ++ Void без указателя

3 голосов
/ 25 августа 2010

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

Конечно, вы можете обойти весь определенный размер, имея

void4
void8
void32

И затем разрешается только «приводить» тип данных void к другому классу, если его размер равен или меньше размера классов.

Есть ли что-то, чего мне не хватает, или комитет C ++ просто рассматриваетэто плохая практика?

РЕДАКТИРОВАТЬ:

Я не очень хорошо объяснил себя, поэтому я приведу пример его использования:

 main()
{
    /* 

     Lets make a list of unknown elements

     std::string is 8 bytes, and float is 4
     bytes, so we'll reserve 8 byte sequences

     */

    vector<void8> elements;

    elements.push_back((void8) string("First string element"));

    elements.push_back((void8) float(5.76) );

    elements.push_back((void8) string("Third string element"));

    // Ect.

    cout << (string) elements[0];
    cout << (float) elements[1];
    cout << (string) elements[2];
    cout << (float) elements[2]; // Garbage


    void1 data;

    data = (void1) bool(1);
    data = (void1) unsigned int(80094); // Error, not enough size
}

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

Ответы [ 10 ]

8 голосов
/ 25 августа 2010

Это называется boost :: option или boost :: any.Это размер максимально допустимого типа данных + sizeof (указатель) и полностью безопасен для типа.

3 голосов
/ 25 августа 2010

В строго типизированном языке все данные имеют тип, поэтому понятие "void" как тип данных отсутствует.В C и C ++ это означает «нет данных» (как возвращаемое значение) или «данные, тип которых вы не знаете» (как цель указателя).

Вы предлагаетемежду состоянием «данные, тип которых вы не знаете, но чей размер вы делаете», предположительно как непрозрачная версия типа, который вы передаете по значению.Помимо того, что это довольно опасная вещь (так как вам приходится вручную обновлять весь код, используя непрозрачный тип, когда вы изменяете размер реального типа), это уже можно сделать без добавления странных расширений в язык, например:

struct void8 { char bytes[8]; };

Этот может использоваться вместе с reinterpret_cast для передачи типов POD в виде непрозрачных комков, во многом так, как вы предлагаете.Использование его с не POD-типами даже более вероятно вызовет неопределенное поведение, чем использование void* для ссылки на не-POD-типы.

Было бы безопаснее и более идиоматично обрабатывать непрозрачные типы как указатели или ссылкиименованные типы, которые были объявлены, но не определены, или что-то вроде boost::any, если вы хотите семантику значений.В C ++ редко требуется использовать void в качестве заполнителя.

2 голосов
/ 25 августа 2010

То, что вы ищете, уже существует.Это называется char.Массив char может использоваться для хранения неизвестных объектов, потому что char - это, в основном, имя C ++ для байта.Таким образом, для хранения неизвестных или переменных типов объектов в одном массиве вы используете массив байтов, а не массив ничего, который будет void.

Точка в указателе void состоит в том, чтомы не знаем на что это указывает.Мы не знаем размер объекта, на который он указывает.Так что void4 не имеет особого смысла.Это больше не «пустота», если мы знаем размер объекта.Единственное, что мы можем сделать с неизвестным объектом - это указать на него.Мы не можем хранить его где-либо, потому что мы не знаем, является ли он объектом POD, и мы не знаем, насколько он велик, или его требования к выравниванию.Поэтому мы, конечно, не храним его в массиве.Все, что мы можем сделать, это создать указатель на него, и у нас уже есть void указатели для этого.

И, конечно, забавный маленький вопрос:

Что здесь типа T?

void foo(void* p) {
   T q = *p;
}

void4?void32?Или просто void?Насколько большим должен быть объект?Что мы знаем об этом?Это тип POD?

2 голосов
/ 25 августа 2010

Что такое пустота? Это ничто, пустота. Void32, лол! void используется для обозначения функции, которая ничего не возвращает. В других языках есть ключевое слово «процедура» или «суб». Указатель на void - указатель на неизвестное (второе использование void). Это две цели, которые служат пустоте.

Обновление: я думаю, что автор хочет обозначить неизвестный тип с известным размером. void32 * - указатель на некоторый объект размером 32 бита, void8 * - указатель на 8-разрядный объект и т. Но его легко эмулировать с помощью int32 *, char * без расширения языка.

2 голосов
/ 25 августа 2010

Что будет означать тип данных void? Я не думаю, что есть действительный, поэтому, вероятно, поэтому он не существует.

0 голосов
/ 25 августа 2010

Если бы существовал тип данных void, я думаю, он не должен представлять ничего и просто проглотить все, что хранится в нем.

Вы можете сказать

(void)func1();

так почему бы и нет

void x;
x = func1();

или

void func2() {
   void x;
   ...
   return x;
}

и в качестве аргументов функции

int func3(int x, void y, char z);

void x = func3(1,2);
x = func3(1,x,2);

Использование void в выражении является ошибкой

Я вижу использование этого в некоторых шаблонах.

0 голосов
/ 25 августа 2010

Я собираюсь предположить, что вы знаете немного больше о вещах, которые вы будете хранить, чем просто их размер, иначе я не верю, что есть смысл хранить эти предметы.

Я думаючто вы можете взглянуть на союзы.Объединение резервирует достаточно места для размещения самого большого члена объединения, а затем в зависимости от того, как вы ссылаетесь на объединение, выбирает «подходящий» объем пространства и предоставляет его в качестве запрашиваемого вами типа.очень похоже на приведение массива символов к тому типу, который вы на самом деле ищете, вы должны хорошо подумать, прежде чем использовать эту функцию.

0 голосов
/ 25 августа 2010

void является «необитаемым» типом, то есть нет возможных значений типа void. Поскольку нет возможных значений, для хранения void не требуется места. Следовательно, значения void будут бессмысленными.

Отступив на мгновение: C и C ++ довольно последовательно распознают void как означающее «ничто». Вы можете иметь указатель на ничто и использовать его для переноса значения указателя на что-то вокруг, но вы не можете разыменовать его - void не имеет значения, с которым вы можете что-либо сделать.

Также обратите внимание, что void -is-ничто переносится в регистр пустых указателей: в то время как некоторые компиляторы, такие как GNU, позволяют выполнять арифметику указателей для значений void*, как если бы они были char*, стандарты Запретите арифметику указателя на void*, поскольку, поскольку void - ничто, он не имеет значимого размера.

Итак, я думаю, что ответ: это было бы бессмысленно. void - это ничто, и вы ничего не можете хранить в значении.

0 голосов
/ 25 августа 2010

void* не является указателем, который является пустым, как недопустимый. Это указатель на пустоту, поскольку там ничего нет.

Тип типа void сам по себе определяется отсутствием значения. В его представлении нет битов. Он не может образовывать объекты.

То, что вы описываете, может быть приведено к и от. Поэтому он содержит информацию. Поэтому это не пустота.

То, что вы описываете, это просто int, где числовое значение игнорируется. Но предлагаемое использование - плохая практика.

0 голосов
/ 25 августа 2010

Наличие типа данных void излишне усложнит ситуацию. Более того, что будет делать тип данных, если он называется void.

Полагаю, вы имеете в виду тип данных, который может функционировать как пустой, но вы можете изменить имя и не называть его пустым.

...