Списки инициализации в стиле C в C ++, структуры и конструкторы классов - PullRequest
3 голосов
/ 24 августа 2011

Я все еще на пути к просветлению в C ++, так что терпите меня ...

Предположим, у меня есть структура:

struct MyThing 
{
    int a, b;
};

Мне хочется создать его, используя сокращение в стиле c, рис.1:

MyThing mt = { 1, 2 };

Тогда предположим, что я решил внедрить метод где-нибудь в моей структуре, и (будучи таким человеком), я чувствую, что структуры не очень подходят методам, поэтому превратите его в класс:

class MyThing 
{
public:
    int a, b;
    int sum() 
    {
        return a + b;
    }
};

Мой рис.1 по-прежнему работает нормально - все чертовски дорого. Тогда я решаю, что в конечном итоге мне понадобится приватный метод и член:

class MyThing 
{
private:
    int c;
    void swap() {
        c = a;
        a = b;
        b = c;
    }
public:
    int a, b;
    int sum() 
    {
        return a + b;
    }
};

В этот момент список инициализации в стиле c на рисунке 1 не компилируется (в любом случае в VS) с «неагрегаты не могут быть инициализированы списком инициализаторов» - что хорошо объясняется здесь: http://msdn.microsoft.com/en-us/library/0s6730bb(v=vs.71).aspx

Итак, я переключаюсь на:

class MyThing 
{
private:
    void swap() {
        int c = a;
        a = b;
        b = c;
    }
public:
    int a, b;
    MyThing (int _a, int _b) : a(_a), b(_b) {}
    int sum() 
    {
        return a + b;
    }
};

затем измените Рис.1 на (Рис.2)

MyThing mt(1, 2);

Оооочень, после всего этого мой вопрос: есть ли какая-то польза от использования списков инициализации в стиле c (то есть они быстрее?) Для создания вещей? Или это будет так же хорошо в первую очередь иметь:

struct MyThing
{
    int a, b;
    MyThing(int _a, int _b) : a(_a), b(_b) {}
};

И использовать это как рис.2 с самого начала? Есть ли какой-либо удар по производительности (даже если он незначительный)?

Спасибо!

Ответы [ 2 ]

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

Ну, во-первых, пример, который вы говорите, не работает, на самом деле работает.(Он не завершится ошибкой, пока вы не добавите конструктор)

Теперь запомните, что объект - это просто часть памяти.Следовательно, двоичное изображение

MyThing mt = { 1, 2 };        // Fig A

точно такое же, как

int  mt[2] = { 1, 2};         // Fig B.

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

mt    DW      0x0001        Fig C
      DW      0x0002

Другими словами, нулевые затраты времени выполнения.

Однако, если присутствует ctor, то он должен быть запущен (это часть контракта C ++).(Неизбежно затраты времени выполнения)

Аналогично, частные члены, базовый класс и т. Д. Мешают взаимно-однозначному соответствию, необходимому для обработки назначения времени компиляции, которое мы имеем на рис. С.

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

есть ли какое-либо преимущество в использовании списков инициализации в стиле c (т.е. они быстрее?) Для создания вещей?

Быстрее, медленнее, действительно ли это имеет значение?Как правило, это намного удобнее синтаксически, чем вызов конструкторов.Это одна из причин, по которой C ++ 0x позволяет использовать этот синтаксис для всех объектов.

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

...