Виртуальные столы на анонимных классах

У меня есть что-то подобное этому в моем кодексе:

#include <iostream>
#include <cstdlib>

struct Base
{
  virtual int Virtual() = 0;
};

struct Child
{
  struct : public Base
  {
    virtual int Virtual() { return 1; }
  } First;

  struct : public Base
  {
    virtual int Virtual() { return 2; }
  } Second;
};

int main()
{
  Child child;
  printf("ble: %i\n", ((Base*)&child.First)->Virtual());
  printf("ble: %i\n", ((Base*)&child.Second)->Virtual());

  system("PAUSE");
  return 0;
}

Я ожидал бы, что это даст эту продукцию:

ble: 1
ble: 2

и это делает так, когда собрано под GCC (3.4.5, я верю).

Компилирование и управление этим под Визуальной Студией 2008 однако, дают это:

ble: 2
ble: 2

То, что интересно, является этим, если я даю Полученные из основы имена структур (struct s1 : public Base), это работает правильно.

Какое поведение, если таковые имеются, правильно? ПРОТИВ того, чтобы просто быть prissy, или это придерживается стандарта? Я пропускаю что-то жизненное здесь?

12
задан GhassanPL 17 January 2010 в 19:45
поделиться

3 ответа

Видно, как MSVC становится неправильным от символов отладки. Он генерирует временные имена для анонимных структур соответственно Child :: <Безымянный тип - первый> и Ребенок :: <Безымянный тип-тип> . Однако есть только один VTable, назван Ребенок :: <Безымянный-тег> :: 'vFTable' И оба конструктора используют его. Разное имя для VTable, безусловно, является частью ошибки.

В Connection.microsoft.com есть несколько ошибок. Microsoft.com, которые связаны с анонимными типами, ни один из которых не допускал его до «должен исправить». Не тот, который вы нашли, хотя, афайк. Возможно, обходной путь слишком просто.

2
ответ дан 2 December 2019 в 22:22
поделиться

Один и два .

-121--4349631-

Я думаю, что лучший доступный и активно поддерживаемый рамка - это «Фреймворк Cocoa XML-RPC» Эрика Чарни. В конце концов нет волшебства за XML-RPC, и вы также должны быть довольно довольны веб-сервисами Apple Core (как Джеймс уже упоминал). Если вы хотите избавиться от синтаксиса в стиле Си, я действительно рекомендую рамку Эрика, потому что это не так подробно и относительно приятно работать с.

-121--2712126-

Похоже, что это ошибка в VS 2008, возможно, потому, что она перезаписывает или игнорирует таблицу vtable для первого неименованного класса в пользу таблицы vtable для второго, так как внутренние имена идентичны. (Когда вы называете один явно, внутренние имена vtables больше не идентичны.)

Насколько я могу судить из стандарта, это должно работать так, как вы ожидаете, и gcc прав.

7
ответ дан 2 December 2019 в 22:22
поделиться

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

Мой опыт в том, что да, если вы всегда загружаете все ваши библиотеки, то это съест драгоценную память (из которых вам выделяется только фиксированное количество мегабайт на процесс). У меня были файлы исходного кода весом 300-400 кб (с комментариями), которые съедали 2-3 МБ на экземпляр сценария. Видя, что скрипт получает только 16-32 МБ со многими общими хостами, это лот . Кроме того, обработка таких огромных файлов часто происходит до половины секунды за запрос, что слишком много.

Таким образом, разделение определенно необходимо, и легко сделать с Autoload и консорциумов. Ознакомьтесь с моим ответом на этот вопрос , чтобы узнать несколько предложений о том, как правильно разделить код. Существует также ссылка на вопрос о том, как организовать крупный проект PHP , который дал большие результаты. Я сам нахожусь в процессе выяснения идеальной структуры, а еще не сделал.:)

-121--3153575-

Несколько очевидных

  • Если скорость не критична, выполните код непосредственно из флэш-памяти.
  • Объявите таблицы данных констант с помощью const . Это позволит избежать копирования данных из флэш-памяти в ОЗУ
  • Упакуйте большие таблицы данных плотно, используя наименьшие типы данных, и в правильном порядке, чтобы избежать заполнения.
  • Используйте сжатие для больших наборов данных (если код сжатия не перевешивает данные)
  • Выключите обработку исключений и RTTI.
  • Кто-нибудь упоминал использование -Os?; -)

Сворачивание знаний в данные

Одно из правил философии Unix может помочь сделать код более компактным:

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

Я не могу подсчитать, сколько раз я видел сложную логику ветвления, охватывающую множество страниц, которые можно было сложить в компактную таблицу правил, констант и указателей функций. Конечные автоматы часто могут быть представлены таким образом (State Pattern). Также применяется образец команды. Всё дело в декларативных и императивных стилях программирования.

Коды журнала + двоичные данные вместо текста

Вместо протоколирования обычного текста, кодов событий журнала и двоичных данных. Затем используйте «словарь» для восстановления сообщений о событиях. Сообщения в словаре могут даже содержать спецификаторы формата в стиле printf, так что значения данных события отображаются аккуратно в тексте.

Минимизируйте количество потоков

Каждому потоку необходим собственный блок памяти для стека и TSS. В тех случаях, когда преимущественное использование не требуется, рассмотрите возможность совместного выполнения задач в одном потоке ( совместная многозадачность ).

Используйте пулы памяти вместо накопления

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

Динамическое выделение только при инициализации

Во встроенных системах, в которых только одно приложение работает неопределенно долго, можно использовать динамическое выделение разумным путь, не приводящим к фрагментации: просто динамически выделять один раз в различных процедурах инициализации и никогда не освобождать память. зарезервировать () контейнеры до нужной емкости и не допускать их автоматического роста. Если требуется часто выделять/освобождать буферы данных (например, для коммуникационных пакетов), используйте пулы памяти. Однажды я даже расширил время выполнения C/C + +, чтобы оно прервало мою программу, если что-либо попытается динамически выделить память после последовательности инициализации.

-121--1158390-

Я могу подтвердить, что это известная ошибка в компиляторе VC (и она репо в VC10); два анонимных класса неправильно совместно используют таблицу vtable.

Анонимные структуры не являются частью стандарта C++.

Edit : Анонимные структуры являются своего рода многозначным термином. Это может означать две вещи:

class outer
{
public:
    struct {
        int a;
        int b;
    } m_a; // 1

    struct {
        int c;
    };     // 2

    union {
        int d;
        int e;
    };     // 3
};

1 то, что происходит здесь, лучше название, чем анонимная структура было бы «неназванным структурой». Сам тип структуры не имеет имени, но объект имеет (m_a).

2 также известен как анонимная структура и не является допустимым C++. Нет имени объекта, и идея заключается в том, что вы можете получить доступ к полю «c» непосредственно на объектах типа outer. Компиляция выполняется только из-за расширения компилятора в Visual Studio (завершится сбоем в/Za)

3 Профсоюзы Anonymous, напротив, являются легальными C++.

Я перепутал эти два, потому что здесь мы называем # 1 «анонимной структурой», и провода в моем мозге пересекаются с # 2.

1
ответ дан 2 December 2019 в 22:22
поделиться
Другие вопросы по тегам:

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