1. 値渡し
これは完全に安全であることが保証されており、簡単です。プロファイリングで本当に必要な場合にのみ、より複雑なことを行う
double computeDelta(vector<double> grid, unsigned int index, double newvalue) {
double before = compute(grid);
grid[index] = newvalue;
double after = compute(grid);
return after-before;
}
2. 非 const 参照渡し
これには、発信者があなたを信頼する必要があり、複数のスレッドがある場合はとにかくコピーを作成する必要がある場合があります
// I modify grid in-place, but promise to revert it before exiting
double computeDelta(vector<double> &grid, unsigned int index, double newvalue) {
double before = compute(grid);
// we can do something much more elegant if C++11 lambdas are allowed
struct swapper {
double &value;
double oldvalue;
swapper(double &v, double newvalue) : value(v), oldvalue(v) {
value = newvalue;
}
~swapper() { value = oldvalue; }
} guard(grid[index], newvalue);
double after = compute(grid);
return after-before;
}
3. リードスルー ラッパーを挿入する
これは、コピーを強制せずに const ref を取得する唯一の安全な (const-correct) 方法です。計算がコンテナ型 (または代わりにイテレータ型でテンプレート化され、代わりにイテレータをプロキシする) が必要です。コピーを回避しているにもかかわらず、アクセスパターンによっては遅くなる場合があります
double computeDelta(vector<double> const &grid, unsigned int index, double newvalue) {
double before = compute(grid);
// assuming only operator[] is used by compute
struct overlay {
vector<double> const &base;
unsigned index;
double value;
overlay(vector<double> const &b, unsigned i, double v)
: base(b), index(i), value(v) {}
double operator[] (vector<double>::size_type i) const {
return (i == index) ? value : base[i];
}
vector<double>::size_type size() const { return base.size(); }
};
double after = compute(overlay(grid, index, newvalue));
return after-before;
}