我有一个函数,在概念上应该不会修改参数。参数对象是一个大对象(10000或更多的 vector ),所以我不想创建拷贝。在 C++ 中做这件事的道德方式是什么。
double computeDelta(const vector< double > &grid, unsigned int index, double newvalue) {
// compute something on old grid
double oldvalue = grid[index]
// change grid temporarily
grid[index] = newvalue; // this is illegal because of const (How to do this is question)
// compute something on new grid
// restore original grid
grid[index] = oldvalue
return // difference of old thing and new thing
}
最佳答案
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。通过非常量引用传递
这需要调用者信任你,如果有多个线程,他们可能无论如何都要复制一份
// 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;
}
关于c++ - 临时修改const参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17368993/