1

我有一些这样的代码,其中 vec 是某种矢量类:

Vec Vec::choose(const Vec& ifPositive, const Vec& ifNegative) const {
    Vec out(mSize);
    for(int index = 0; index < mSize; ++index) {
        if(mData[i] > 0)
            out[i] = ifPositive[i];
        else
            out[i] = ifNegative[i];
    }
    return out;
}

现在这段代码通常可以正常工作,但是如果函数的左侧是参数之一,则有一些不必要的构造函数/析构函数调用:

curVal =  trigger.choose(posVal, curVal); // construct is called in choose, then old curVal is destroyed

有什么方法可以改善/避免这种情况,比如编译器是否看到函数的左侧是运行不同代码的参数之一?

编辑:这里是一些示例代码:http: //ideone.com/nPUK3h

我想知道是否可以省略最后 (4.) 构造。我稍后会在家里用一些更复杂的优化来编译它。

Edit2:如果我引入以下附加功能,我可以避免额外的构造:

Vec& Vec::setNegative(Vec& target, const Vec& ifNegative) const {
   for(int index = 0; index < mSize; ++index) {
        if(mData[index] <= 0)
            target[index] = ifNegative[index];
    }
    return target;
}

因此,如果选择函数的 lhs 与第一个参数相同,则会产生相同的输出,但是如果 lhs 是另一个向量,我希望得到一个新向量。

有没有办法通过一些模板魔术或编译器技术在两者之间进行选择?

4

2 回答 2

1

IIRC,RVO 允许编译器在接收对象的位置构造返回值,但在这种情况下,调用中使用了对该对象的引用,即在使用参数之前构造返回值。

所以我可以看到这将如何击败 RVO。我不明白为什么它会打败移动。

于 2013-06-27T12:29:05.810 回答
0

使用具有移动语义的 C++11 编译器。返回的Vec对象是无名的,可以从中移动。

请记住,所编写的代码是高度异常安全的。如果任何分配失败,curVal则保持不变。任何通过动态修改起作用的“优化”curVal都可能打破这一点。

于 2013-06-27T11:04:19.693 回答