使一个数学向量类具有初始化器列表意识

Make a math vector class to be initializer list aware

本文关键字:初始化 意识 列表 向量 一个      更新时间:2023-10-16

我有一个数学向量类,设计如下:

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%以上

Brace初始化适用于所有类型的构造函数,在这种情况下不需要初始化器列表构造函数参数。相反,初始化器列表用于变量内容,就像动态容器的内容一样,但不用于固定长度的构造函数参数。所以你可以说:

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向量类型,而根本不需要编写自定义类。)

最后,您可以在最后一个制作向量列表的示例中组合构造初始值设定项列表和初始值设定值列表构造函数:

std::list<Vector3D> l { { 1.0, 2.0, 3.0}, { 1.5, 3.0, 4.4 }, { 0.0, -1.2, 4.1 } };