Typedefs, (двоичный код) дублирование кода и объектный файл - PullRequest
1 голос
/ 17 декабря 2010

Предположим, что я скомпилировал файл исходного файла, который содержит этот фрагмент кода,

struct Point
{
    int x;
    int y;
};

struct Size
{
    int x;
    int y;
};

Поскольку Point и Size точно такие же (с точки зрения структуры памяти его членов), будет ликомпилятор генерирует повторяющийся код (по одному для каждого struct) в объектном файле?Это мой первый вопрос.


Теперь давайте удалим struct Size из исходного кода и определим его, используя вместо этого typedef, например,

typedef Point Size;

Чтобудет ли компиляция делать сейчас?Будет ли дублировать код (поскольку typedef - это не просто переименование, а нечто большее)?


Теперь предположим, что у нас есть шаблон класса, подобный следующему:

template <int UnUsed>
class ConcreteError : public BaseError {
public:
    ConcreteError () :BaseError(), error_msg() {}

    ConcreteError (int errorCode, int osErrorCode, const std::string& errorMessage)
        :BaseError(errorCode, osErrorCode, errorMessage){}
};

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

typedef ConcreteError<0> FileError;
typedef ConcreteError<1> NetworkError;
typedef ConcreteError<2> DatabaseError;

Поскольку параметр шаблона int UnUsed не используется в реализации класса (предположим, что), поэтому, похоже, что эта ситуация точно такая же, как у нескольких классовпри точно такой же структуре памяти (как в случае struct Point и struct Size), будет ли дублированный код в объектном файле?

А что если мы сделаем так, то

typedef ConcreteError<0> FileError;
typedef ConcreteError<0> NetworkError;
typedef ConcreteError<0> DatabaseError;

Будет ли эта ситуация лучше, поскольку теперь мы используем тот же экземплярный класс в typedefs?

PS: этот код шаблона класса взят здесь:

Как создать производные классы из базового класса с помощью шаблонного программирования на C ++?


На самом деле, я понятия не имею, как компилятор генерирует объектный файл из исходного кода, и как он обрабатывает имена классов, их членов, другие символы и все.Как это обрабатывает typedefs?Что это делает с этим,

typedef int ArrayInt[100];

Тип ArrayInt новый здесь?Какой компилятор кода создает для него в объектном файле?Где хранится 100?

Ответы [ 3 ]

2 голосов
/ 17 декабря 2010

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

Данные в объектном файле делятся на три сегмента: код, статические данные и постоянные данные.

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

Статические данные генерируются путем определения глобальных переменных, статических переменных-членов (опять же, фактических определений).а не только объявления внутри класса) и статические локальные переменные.Переменная не должна быть объявлена ​​с модификатором const для перехода к сегменту статических данных.

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

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

Если только я действительно не пропустил что-то, ничто другое в программе не генерирует никаких данных в объектном файле, особенно объявления и определения типов,Они используются внутри компилятором.Поэтому, когда компилятор видит определение структуры, он вспоминает, что он состоит из двух 32-разрядных целых чисел.Когда он находит некоторый реальный код, который использует эту структуру, он знает, что он должен сгенерировать код, который работает с двумя 32-битными целыми числами, должен выделить как минимум 8 байтов для его хранения и так далее.Но вся эта информация используется внутри во время компиляции и на самом деле не входит в объектный файл.Если бы в C ++ было что-то вроде отражения, это была бы другая история.

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

2 голосов
/ 17 декабря 2010

Во-первых, код для первых включенных вами определений структуры не создается, поэтому сравнивать два типа бессмысленно.Но в C ++ имена типов важны, поэтому struct A определенно обрабатывается отдельно от struct B.

typedef создает псевдонимы типов, поэтому typedef-ed тип равен действительно, оригинальный тип (он не создает другого типа).

ConcreteError<0> - это тип, отличный от ConcreteError<1>.

Я не думаю, что что-то мешает компиляторуПрикольные и псевдонимы искаженных имен функций для одного и того же кода, когда параметры идентичны с точки зрения размещения данных, и функциям не нужно вызывать другие подфункции данных, которые имеют разные фактические типы, и функции делают вещи, эквивалентные обоим типам1014 *, но я не думаю, что это действительно делается на практике .Фактически существуют компиляторы (см. Комментарий Бена ниже).

Для последнего определения типа (все псевдонимы ConcreteError<0>) создается только одна "версия" ConcreteError (потому что только этапроиллюстрированный).

0 голосов
/ 17 декабря 2010

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

Нет, дублирующего кода с псевдонимами нет.На самом деле вообще нет кода.

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

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

Нет, это псевдоним для int [100].

В значительной степенивопрос о том, «сколько машинного кода получается из этой конструкции», полностью зависит от реализации.

...