假设我有一个Foo
课程,其vector_
数据成员如此:
class Foo {
public:
const std::vector<int> & vector() const {
return vector_;
}
void vector(const std::vector<int> &vector) {
vector_ = vector;
// Other operations which need to be done after the
// vector_ member has changed
}
private:
// Some large vector
std::vector<int> vector_;
};
我经常遇到像这样的情况
void someOperation(std::vector<int> &v) {
// Operate on v, but almost always let v's size constant
}
int main() {
// Create Foo object
Foo foo;
// Long loop
for (auto k = 0; k < 100; k++) {
auto v = foo.vector();
someOperation(v);
foo.vector(v);
}
}
由于(foo
- 正确)vector_
的实现,我无法将someOperation
的(可能很大的)const
成员直接传递给vector
1}}访问成员的方法。虽然someOperation
几乎总是让其参数的大小保持不变,但我需要先复制向量,然后将其传递给someOperation
,然后传递给foo
的setter。显然,如果删除const
类getter的Foo
- 并在成员被{{1}更改后调用afterChange
方法,我可以避免使用此额外副本} - 但这打破了封装:
someOperation
还有其他选择吗?或者这是打破封装合法的情况之一?
答案 0 :(得分:3)
在你的情况下,你可以通过将矢量移出类并再次返回来获得一些效率:
class Foo {
public:
std::vector<int>&& take_vector() {
return std::move(vector_);
}
void vector(std::vector<int> vector) {
vector_ = std::move(vector);
// Other operations which need to be done after the
// vector_ member has changed
}
private:
// Some large vector
std::vector<int> vector_;
};
...然后
void someOperation(std::vector<int> &v) {
// Operate on v, but almost always let v's size constant
}
int main() {
// Create Foo object
Foo foo;
// Long loop
for (auto k = 0; k < 100; k++) {
// this is a very cheap move
auto v = foo.take_vector();
someOperation(v);
// so is this
foo.vector(std::move(v));
}
}
或者您可以将矢量的操作构建为访问者:
class Foo {
public:
template<class F>
void apply_op(F&& op) {
op(vector_);
// Other operations which need to be done after the
// vector_ member has changed
}
private:
// Some large vector
std::vector<int> vector_;
};
像这样调用:
void someOperation(std::vector<int> &v) {
// Operate on v, but almost always let v's size constant
}
int main() {
// Create Foo object
Foo foo;
// Long loop
for (auto k = 0; k < 100; k++)
{
foo.apply_op(&someOperation);
}
}
答案 1 :(得分:0)
在您的情况下,您只需更改someOperation()
即可在范围内工作,而不是向量本身。然后,您的Foo
类需要begin()
和end()
函数,并返回适当的迭代器。