2009-11-30 191 views
1

我有一个矢量类,有加法,乘法,减法,除法等运算符。我试图优化我的程序(它执行了很多矢量操作),并且我意识到花费的时间大约有50%是在构建和破坏矢量。我知道这是因为每次我为矢量调用一个非复合数学运算符时,都会构造一个新矢量。有没有一种方法来防止这种情况,而不使用复合运算符或扩展向量操作?在非复合操作中有没有办法阻止施工?

如果我有:

Vector a = Vector(x, y, z); 
Vector b = Vector(a, b, c); 

Vector c = a + b; 

我不能使用+ =,因为c是一个完全新的载体。我知道我可以加速它:

c.x = a.x + b.x; 
c.y = a.y + b.y; 
c.z = a.z + b.z; 

但这看起来不像使用运算符那样干净。

回答

2

我明白,这是因为每 我称之为非复合 数学运算的矢量时间,一个新的 载体构建。有没有 的方法来防止这种情况,而不使用 复合运算符或扩展向量 操作?

好了,把两个东西放在一起,产生第三件事需要您构建第三件事情的性质......因此,如何你问甚至逻辑上可能的?这就是说,如果您担心使用加法运算符创建的临时对象,那么如果您的编译器支持返回值优化,那么可以通过编译器对这些临时对象进行优化。或者,如果你的编译器不支持这一点,并且你真的想减少临时对象,但保留+运算符,你可能需要考虑模拟C++ 0x移动语义,并为你的向量提供一个右值移动构造函数,将在按值返回临时值时被调用。有关在C++ 03中实现移动语义的信息,请参阅this article中标题为“移动对象”的部分。一旦C++ 0x出来,你可以用真正的移动构造函数替换这些黑客,使用&&运算符来实现右值引用。

+0

那么假设第三个向量已经被构造了。我只想修改其组件,而不是创建一个新的矢量,并将新矢量的组件复制到已经构建好的组件中。这是浪费。另外,如果我在一行中执行多个操作,则将为每个这些操作创建一个新的向量,这是不必要的。 – Stewart 2009-11-30 02:02:05

+1

减少创建的临时对象的一个​​好方法是通过为Vector类实现移动构造函数和移动赋值运算符来模拟C++ 0x移动语义。你需要将你返回的临时对象封装成类似于MyVector_move_t类的类。请参阅我编辑帖子中提到的文章,了解更多关于此操作的信息。最好的部分是,当C++ 0x出现时,您可以用真正的移动构造函数替换假的移动构造函数。 – 2009-11-30 02:11:40

1

请确保您打开了优化,并且您的编译器正在应用RVO,这是专门针对这种情况而设计的(但不是必需使用的)。 (您可能必须在op +实现中使用一种形式的NRVO,下面的示例可帮助编译器识别并应用RVO。)另外,您是否看过blitz++

Vector operator+(Vector const& a, Vector const& b) { 
    Vector nrvo; 
    // or: Vector nrvo (ctor, parameters, here); 
    //... 
    return nrvo; 
} 

有其他方法也一样,比如做一个明确的副本,然后使用运算+ =,供应在一个情况下RVO不适:

Vector c; // created somewhere else, and we want to assign to it 
// instead of create it "in-place" as RVO does 

Vector a, b; 
// instead of: 
//c = a + b 
// use: 
c = a; 
c += b; 

这可能是用expression templates实现,就像blitz + ++的用法一样,不需要从c = a + b改变你的语法。

1

哇。你的代码是完全低效的:

Vector a = Vector(x, y, z); 
Vector b = Vector(a, b, c); 

这只是效率低下。你想写的是

Vector a(x, y, z); 
Vector b(a, b, c); 
相关问题