【问题标题】:Is there a way to prevent construction during non-compound operations?有没有办法防止非复合操作期间的施工?
【发布时间】:2009-11-30 01:49:09
【问题描述】:

我有一个向量类,它有加法、乘法、减法、除法等运算符。我正在尝试优化我的程序(它执行大量向量操作),并且我意识到大约 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;

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

【问题讨论】:

    标签: c++


    【解决方案1】:

    我明白这是因为 每次我调用非复合 向量的数学运算符,a 构建了新的向量。有没有 在不使用的情况下防止这种情况的方法 复合运算符或扩展向量 操作?

    嗯,将两个东西加在一起产生第三个东西的性质要求你构建第三个东西......那么你问的问题在逻辑上怎么可能?

    话虽如此,如果您担心使用加法运算符创建的临时变量,如果您的编译器支持返回值优化,编译器可能会优化这些临时变量。或者,如果您的编译器不支持这一点并且您确实想减少临时变量但保留 + 运算符,您可能需要研究模拟 C++0x 移动语义,并为您的向量提供右值移动构造函数, 当它返回一个临时值时将被调用。有关在 C++03 中实现移动语义的信息,请参阅 this article 中标题为“移动对象”的部分。一旦 C++0x 出现,您就可以使用 && 运算符作为右值引用,将这些技巧替换为真正的移动构造函数。

    【讨论】:

    • 那么假设第三个向量已经构建好了。我只想修改它的组件,而不是创建一个新向量并将新向量的组件复制到已经构建的向量中。这是一种浪费。此外,如果我在一行中执行多个操作,则会为这些操作中的每一个创建一个新向量,这是不必要的。
    • 减少临时创建的可靠方法是通过为 Vector 类实现移动构造函数和移动赋值运算符来模拟 C++0x 移动语义。您需要将返回的临时对象包装在 MyVector_move_t 类之类的东西中。有关执行此操作的更多信息,请参阅我在经过编辑的帖子中引用的文章。最好的部分是当 C++0x 出现时,你可以用真正的移动构造函数替换你的假移动构造函数。
    【解决方案2】:

    确保您已启用优化并且您的编译器正在应用 RVO,它正是为这种情况而设计的(但不是必须使用的)。 (您可能必须在您的 op+ 实现中使用一种 NRVO 形式,例如下面的示例,这有助于编译器识别和应用 RVO。)另外,您看过 blitz++ 吗?

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

    还有其他替代方案,例如进行显式复制,然后使用 op+=,这适用于 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 的语法。

    【讨论】:

      【解决方案3】:

      哇哦。您的代码完全低效:

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

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-02-15
        • 1970-01-01
        • 2020-10-10
        • 2018-02-04
        • 2021-02-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多