C++ 与“代理对象更新延迟”相比;避免使用自定义构造和销毁的未命名对象”;
我有一个类C++ 与“代理对象更新延迟”相比;避免使用自定义构造和销毁的未命名对象”;,c++,c++11,c++14,c++17,C++,C++11,C++14,C++17,我有一个类complex,它具有修改某些内部状态的各种setter。这种内部状态修改可能会很昂贵,所以我不想经常这样做。特别是,如果立即连续调用多个setter,我希望在最后一次setter调用之后只执行一次昂贵的内部状态更新 我已通过代理解决了(或“解决”?)该要求。以下是最简单的工作代码示例: #include <iostream> class complicated { public: class proxy { public: pro
complex
,它具有修改某些内部状态的各种setter。这种内部状态修改可能会很昂贵,所以我不想经常这样做。特别是,如果立即连续调用多个setter,我希望在最后一次setter调用之后只执行一次昂贵的内部状态更新
我已通过代理解决了(或“解决”?)该要求。以下是最简单的工作代码示例:
#include <iostream>
class complicated
{
public:
class proxy
{
public:
proxy(complicated& tbu) : to_be_updated(&tbu) {
}
~proxy() {
if (nullptr != to_be_updated) {
to_be_updated->update_internal_state();
}
}
// If the user uses this operator, disable update-call in the destructor!
complicated* operator->() {
auto* ret = to_be_updated;
to_be_updated = nullptr;
return ret;
}
private:
complicated* to_be_updated;
};
public:
proxy set_a(int value) {
std::cout << "set_a" << std::endl;
a = value;
return proxy(*this);
}
proxy set_b(int value) {
std::cout << "set_b" << std::endl;
b = value;
return proxy(*this);
}
proxy set_c(int value) {
std::cout << "set_c" << std::endl;
c = value;
return proxy(*this);
}
void update_internal_state() {
std::cout << "update" << std::endl;
expensive_to_compute_internal_state = a + b + c;
}
private:
int a;
int b;
int c;
int expensive_to_compute_internal_state;
};
int main()
{
complicated x;
x.set_a(1);
std::cout << std::endl;
x.set_a(1)->set_b(2);
std::cout << std::endl;
x.set_a(1)->set_b(2)->set_c(3);
}
#包括
班级复杂
{
公众:
类代理
{
公众:
代理(复杂和待定):待更新(&待定){
}
~proxy(){
如果(nullptr!=待更新){
更新->更新内部状态();
}
}
//如果用户使用此运算符,请禁用析构函数中的更新调用!
复杂*运算符->(){
自动*ret=待更新;
待更新=nullptr;
返回ret;
}
私人:
复杂*待更新;
};
公众:
代理集_a(int值){
std::cout我认为您的解决方案是合法的,但它有一个缺点,即它对代码用户隐藏,更新成本很高,因此人们更可能会写:
x.set_a(1);
x.set_b(2);
我建议将setters设置为私有,并添加一个friend事务类,以便修改对象如下所示:
complicated x;
{
transaction t(x);
t.set_a(1);
t.set_b(2);
// implicit commit may be also done in destructor
t.commit();
}
如果事务
将是修改复杂
的唯一方法-用户更倾向于在一个事务中调用多个setter。我在这里看到的危险是,如果您的类有任何不返回代理(或任何公共成员)的方法。如果使用代理的操作符->
,则禁用更新调用(这会产生复杂的
),但只有在使用操作符->
总是会产生另一个代理对象来接管更新任务时,这才是安全的。对于以后修改类的任何人来说,这似乎是一个巨大的陷阱
我认为,如果complex
能够跟踪在其上创建的活动proxy
对象的数量,以便最后一个要销毁的proxy
执行更新调用,那么会更安全。根据人们选择“错误”方法的论点,您可能会把事情简单一点(特别是从用户的角度):
这样,您将只在需要时执行计算,而不需要像代理对象或显式事务这样的附加扩展
根据您的需要,您可能会将此模式封装在单独的(模板?)类中,可能会接收更新程序对象(lambda?),或者使用纯虚拟的update
函数来重复更少的代码
旁注:设置一个值可能会使多个缓存值无效–没问题,请将多个脏标志设置为true,然后…至少没有警告,您能指出出现此警告的正确行吗?您能否不只是手动更新?警告显示在每行中,其中至少调用了一个设置程序,例如x.set_a(1);
。它指的是返回的临时代理
对象。如果它正常工作,可能更好地位于?@Aconcagua谢谢你的指针。我不知道CodeReview的存在!StackOverflow和CodeReview之间的界限在哪里?哦,这是一个非常好的观点。谢谢。除此之外,还有关于警告的想法吗惯性导航与制导?
complicated x;
{
transaction t(x);
t.set_a(1);
t.set_b(2);
// implicit commit may be also done in destructor
t.commit();
}
class Demo
{
int m_x
int m_y; // cached value, result of complex calculation
bool m_isDirtyY;
public:
int x() { return m_x; }
void x(int value) { m_x = value; m_isDirtyY = true; }
int y()
{
if(m_isDirtyY)
{
// complex calculations...
m_y = result;
m_isDirtyY = false;
}
return m_y;
}
};