PODs и VPtr Design в компиляторах C ++ - PullRequest
1 голос
/ 05 декабря 2011

Этот вопрос больше касается языкового дизайна, а не об изменении соглашений C ++.

Размышляя о языке программирования Go (как его очистка отделяет данные от интерфейсов, эффективно превращая все объекты в структуры) и POD в C ++ (мне нравится memset / memcpy при выделении gazillion небольших структуроподобных объектов), я интересовался соглашением C ++ о присоединении vptr непосредственно к экземпляру объекта , что испортило компоновку.

Это требование или просто соглашение?

Если бы вы разрабатывали альтернативный компилятор, могли бы вы вместо этого иметь большую внешнюю справочную таблицу для vptrs? Например, такую ​​структуру, как map<void*,vptr>? Все экземпляры были бы POD, в отношении настроек памяти, и для поиска его vptr мы взяли бы его адрес и заглянули внутрь большой внешней справочной таблицы.

Недостаток в том, что все требует поиска. Это жизнеспособный альтернативный дизайн или есть серьезные недостатки?

Ответы [ 4 ]

3 голосов
/ 05 декабря 2011

Производительность очень вероятно пострадает. Некоторые языки добавляют какое-то кэширование для поиска методов.

Вы можете найти способ вызова метода для данного селектора (или имени метода) другим способом. Посмотрите на Smalltalk или Self или Javascript или Система Common Lisp Object или Ocaml

Однако в некоторых языках реализация содержит хитрые трюки (кэширование, JIT и т. Д.), Которые делают их такими же быстрыми, как C ++ (но это проблема реализации, а не проблема языкового дизайна).

2 голосов
/ 05 декабря 2011

Эта карта должна хранить те void* указатели, которые, вероятно, имеют размер vptr, так что на самом деле используется больше памяти, так как vptr s также нужно будет хранить.И поиск по карте не тривиален - если есть столкновение, вы должны выполнять линейный поиск, пока не будет найдено точное совпадение.Таким образом, поиск будет в среднем медленнее и будет использоваться больше памяти.

Фактически добавление объекта с vptr не мешает компоновке - подобъекты размещаются точно так же, как и без vptr.

1 голос
/ 05 декабря 2011

C ++ не обязательно должен иметь v-таблицу, хотя это путь, по которому пошли все основные компиляторы.

Вы не получите указатель vtable, если у вас нет виртуальных методов.Если вы не хотите, то не используйте виртуальный.Если вам нужен только POD, тогда используйте C.

Если вы разрабатываете альтернативный компилятор, вы могли бы вместо этого иметь большую внешнюю справочную таблицу для vptrs?Например, структура как карта?Все экземпляры были бы POD, в отношении настроек памяти, и для поиска его vptr мы взяли бы его адрес и заглянули внутрь большой внешней справочной таблицы.

Что это решает?memset все равно не будет работать правильно - он ломает ссылки, обходя методы копирования.Это также не решает динамическую диспетчеризацию, поскольку memset не регистрирует тип на карте.

0 голосов
/ 05 декабря 2011

Все экземпляры будут POD

Здесь есть грубое недоразумение.

Существует очень существенная разница между классом с виртуальными методами и не POD: конструкторы копирования существуют по причине.

Простой пример (упрощенный):

template <typename T>
class unique_ptr {
public:
  unique_ptr(): _ptr(nullptr) {}
  explicit unique_ptr(T* p): _ptr(p) {}

  unique_ptr(unique_ptr const&) = delete;
  unique_ptr(unique_ptr&& other): _ptr(other._ptr) { other._ptr = 0; }

  unique_ptr& operator=(unique_ptr other) {
    std::swap(_ptr, other._ptr);
    return *this;
  }

  ~unique_ptr() { delete _ptr; }

  T& operator*() const { return *_ptr; }
  T* operator->() const { return _ptr; }

private:
  T* _ptr;
}; // class unique_ptr<T>

Этот класс является POD с точки зрения макета.Однако memcpy было бы вопиющим нарушением условий использования и привело бы к неопределенному поведению: конструктор копирования был удален по причине!

Пока нет виртуального метода.

Любой классчто владеет памятью, прямо или косвенно, это не POD.Учитывая количество классов в реальном использовании, которое включает std::string ... это довольно распространенный сценарий.

А как насчет Go тогда?Существует сборщик мусора ...

Теперь это не означает, что классы должны создаваться с помощью виртуальных методов (и, следовательно, виртуальных указателей), но это, безусловно, проще сделать.Я лично фанат Shims, однако возникают проблемы с владением памятью / сроками жизни объектов.

...