押して操作する軽いオブジェクトがいくつかあるので、それらをより複雑なものに含めたいと思います。変更しないままにしておくべきルックアップ テーブルがあります。アイデアは単純に見えますが、これを行う 1 行で --b += c(a);
高価な一時ファイルが作成されます。
#include <vector>
static int count;
struct costly {
/* std::map<std::string, int> and whatnot */
int b;
~costly() { count++; }
costly(int b): b(b) { }
costly &operator+= (costly &rhs) { b += rhs.b; return *this; }
};
/* Note the assumption above constructor exists for rhs */
costly operator* (const costly &lhs, costly rhs) {
rhs.b *= lhs.b; return rhs;
}
struct cheap {
/* Consider these private or generally unaccessible to 'costly' */
int index, mul;
cheap(int index, int mul): index(index), mul(mul) { }
costly operator() (const std::vector<costly> &rhs) {
/* Can we do without this? */
costly tmp = rhs[index] * mul; return tmp;
}
};
int main(int argc, char* argv[]) {
std::vector<costly> a = {1, 2}; costly b(1); cheap c = {1, 2};
/* Above init also calls the destructor, don't care for now */
count = 0;
b += c(a);
return count;
}
私は RVO と C++11 の右辺値について調べてきましたが、導入された中間体を完全に排除するのに十分なほど頭を包むことはできません。上記では、rhs のコンストラクターが使用可能であるため、1 つしか作成しません。最初はこれを持っていました。
costly operator* (costly lhs, int rhs) {
lhs.b *= rhs; return lhs;
}
/* ... */
costly operator() (const std::vector<costly> &rhs) {
return rhs[index] * mul;
}
しかし、私の直感に反して、結果はcount
2 でさえありました。コンパイラが私の意図を理解していないのはなぜですか?