Сделайте математический векторный класс, чтобы быть осведомленным о списке инициализатора - PullRequest
2 голосов
/ 04 февраля 2012

У меня есть математический векторный класс, который разработан следующим образом:

class Vector3D {
public:
    float x;
    float y;
    float z;

public:
    Vector3D() {}
    Vector3D(float xx, float yy, float zz = 0.0) { x=xx; y=yy; z=zz; }
    Vector3D(const float v[]) { x=v[0]; y=v[1]; z=v[2]; }
    Vector3D(const Vector3D& v) { x=v.x; y=v.y; z=v.z; }

    // math member methods
    // ...
};

Я использовал следующее для создания переменной типа Vector3D в стеке:

Vector3D vec1 = Vector3D(1.0, 1.0, 1.0);

Я слышал, что можно сократить это с помощью C ++ 0x, реализовав конструктор списка инициализаторов, так что можно будет написать что-то вроде:

Vector3D vec1 = { 1.0, 1.0, 1.0 };

Как правильно это реализовать?

Обновление

Синтаксис фигурных скобок действительно работает из коробки для этого класса! Спасибо за ответ и комментарии!

Кроме того, я провел несколько синтетических тестов производительности, пытаясь измерить, дает ли список инициализатора конструктора ускорение по сравнению с присваиванием переменной члена в конструкторе. Ниже приведены результаты, полученные с помощью g ++ 4.6.1:

  1. Как есть (назначение члена в конструкторе и конструкторе нестандартного копирования):

    Median:       634860 ns
    Median, CPI:  15.8715 ns
    Average:      636614 ns
    Average, CPI: 15.9154 ns 
    
  2. Использование списка инициализатора конструктора и пользовательского конструктора копирования:

    Median:       634928 ns
    Median, CPI:  15.8732 ns
    Average:      636312 ns
    Average, CPI: 15.9078 ns
    
  3. Использование списка инициализатора конструктора и конструктора копирования по умолчанию:

    Median:       860337 ns
    Median, CPI:  21.5084 ns
    Average:      864391 ns
    Average, CPI: 21.6098 ns
    

Некоторые выводы:

  • Список инициализатора конструктора не дает ускорения по сравнению с присваиванием переменной-члена в случае класса математических векторов, представленного выше.
  • Пользовательский конструктор копирования работает более чем на 35% быстрее, чем конструктор копирования по умолчанию.

1 Ответ

6 голосов
/ 04 февраля 2012

Brace-initialization работает для всех видов конструкторов, и в этом случае вам не нужен аргумент конструктора списка инициализаторов. Напротив, списки инициализаторов предназначены для переменной содержимого, подобно содержимому динамического контейнера, но не для аргументов конструктора фиксированной длины. Так что вы можете просто сказать:

vector3D v { 1, 1, 1 };

и все будет хорошо.

Обратите внимание, что вы действительно должны инициализировать своих учеников, а не назначать их:

Vector3D(float xx, float yy, float zz = 0.0) : x(xx), y(yy), z(zz) { }
Vector3D(const float v[]) : x(v[0]), y(v[1]), z(v[2]) { }

Вы также не должны писать конструктор копирования, так как он не лучше, чем тот, который предоставляется по умолчанию. То же самое касается оператора присваивания.

(Лично я не чувствую себя комфортно с конструктором float[]; было бы лучше использовать std::array<float, 3>; но опять же, вы можете просто использовать такой массив как ваш 3D-векторный тип с самого начала и вообще не надо писать собственный класс.)

Наконец, вы можете объединить construct-initializer-lists и initializer-list-constructors в этом последнем примере создания списка векторов:

std::list<Vector3D> l { { 1.0, 2.0, 3.0}, { 1.5, 3.0, 4.4 }, { 0.0, -1.2, 4.1 } };
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...