使用堆栈将成员变量重置为原始值的一般方法?

我遇到了需要临时更改类实例变量的类实例函数,然后在函数完成时将其恢复。该函数在所有地方都有return语句,并且在每次返回之前都有一个恢复语句。这对我来说似乎很混乱,更不用说提出异常时可怕了。使用堆栈将成员变量" title="成员变量">成员变量重置为原始值的一般方法?

作为一种改进,我想出了使用内部类定义的泛化。这是一个示例驱动程序(类恢复器)。

class Unwind { 

private:

bool b_active_; ///< the thing I want to be restored

template<typename T>

class restorer {

T* ref_;

T save_;

public:

restorer(T* perm) : ref_(perm), save_(*ref_) {};

~restorer() { *ref_ = save_; }

};

public:

Unwind() : b_active_(false) {};

void a() { out("a in"); b(); out("a end"); }

void b() {

out("b in");

{

restorer<bool> trust_in_the_stack(&b_active_); // "restorer" created on the stack

b_active_ = true; // change b_active_ only while "within" b()

c();

out("b inner end");

}

out("b end");

}

void c() { out("c in"); d(); out("c end"); }

void d() { out("d in"); cout << "deepest" << endl; out("d end"); }

void out(const std::string& msg) {

std::cout << msg << ": " << b_active_ << std::endl;

}

};

int main() { Unwind u; u.a(); return 0; }

使用克++ 4.2.3(-Wall)输出是:

a in: 0

b in: 0

c in: 1

d in: 1

deepest

d end: 1

c end: 1

b inner end: 1

b end: 0

a end: 0

这正是我期望在 “B端”。

我觉得在类Unwind中定义类恢复器有助于防止滥用。

我的问题是,是否有一个通用和安全的方法来做到这一点? 我很担心有生之年的问题。

编辑:请假定堆栈上没有线程,而是根据此b_active_标志更改行为的“下游”方法。

回答:

我修改基于注释的样本多一点,并放在为社区维基回答,而不是编辑题。

/// c++ code sample 

#ifndef UTIL_RESTORER_HPP

#define UTIL_RESTORER_HPP

namespace Utility {

/// A Restorer instance ("inst") uses the stack to restore a saved

/// value to the named variable when the instance "inst" goes out of

/// scope.

///

/// Restorer is designed to be an auto variable, not allocated on any

/// other memory resource like a heap or in-place.

template<typename T>

class restorer {

T& ref_;

T save_;

public:

restorer(T& perm) : ref_(perm), save_(perm) {}

~restorer() { ref_ = save_; }

};

}//NAMESPACE

#endif//UTIL_RESTORER_HPP

回答:

这就是我将如何做到这一点。这样,如果函数抛出或由于某种原因返回提前,则您的Restorer对象将被销毁并且该变量重置为原始值。真正的问题是,为什么你需要有一个变量在函数返回时被还原?该对象是否使用多个线程?

QuantumPete

回答:

我喜欢的恢复模板,但我可能会把模板开卷类外,甚至在一个单独的头文件,以便它可以在未来其他类重用。这也会使它更具可读性。

回答:

我同意亚当皮尔斯也认为你应该更喜欢指针引用:

template<typename T> 

class restorer {

T& ref_;

T save_;

public:

restorer(T& perm) : ref_(perm), save_(ref_) {};

~restorer() { ref_ = save_; }

};

以上是 使用堆栈将成员变量重置为原始值的一般方法? 的全部内容, 来源链接: utcz.com/qa/260807.html

回到顶部