我做了一个“带作用域的setter”,当变量超出作用域时,它会自动给变量赋值,通常是POD。我主要使用它来跟踪当前是否在某个范围内执行。
template<typename T>
struct FScopedSetter
{
FScopedSetter(T& InObject, T InbOutOfScopeValue)
{
Object = &InObject;
bOutOfScopeValue = InbOutOfScopeValue;
}
virtual ~FScopedSetter()
{
*Object = bOutOfScopeValue;
}
T* Object;
T bOutOfScopeValue;
};
// Example:
bool bInTaskA = false;
void TaskA()
{
bInTaskA = true;
FScopedSetter<bool> Setter(bInTaskA, false);
// ..
}当稍后我决定在TaskA中添加一个额外的返回语句,但忘记在它前面添加bInTaskA = false时,这样应该更安全。
我的问题是:这是正确的吗?假设我命名了FScopedSetter对象,它是否(总是)正确工作,至少在使用PODs时是正确的?我有点担心编译器可能会因为setter没有使用而决定提前结束它的生命周期?
谢谢!
发布于 2019-09-26 20:18:19
不要担心,一个命名的setter对象不会在它的作用域结束之前被销毁。它将像往常一样被销毁:按相反的构造顺序。
然而,在发布的代码中有一些小问题。首先,FScopedSetter的析构函数不必是虚的,因为这里没有继承。
并且T::operator=(const T&)决不能抛出(最好声明为noexcept),否则您的作用域赋值器类的析构函数可能会抛出。如果您的代码是针对C++11的,那么将bOutOfScopeValue迁移到*Object会更好
FScopedSetter(T& InObject, T InbOutOfScopeValue)
: Object(&InObject)
, bOutOfScopeValue(InbOutOfScopeValue)
{
}
~FScopedSetter()
{
static_assert(noexcept(*Object = std::move(bOutOfScopeValue)),
"Move assignment of your data type may throw. Make sure it doesn't.");
*Object = std::move(bOutOfScopeValue);
}访问*Object可能需要同步,这取决于“任务”是否与“线程”有关。
发布于 2019-09-26 20:17:44
一般来说,这个想法似乎很好。但是,最好使用shared_ptr<>来确保依赖对象不会太快超出作用域,因为这会使程序崩溃。
template<typename T>
struct FScopedSetter
{
FScopedSetter(std::shared_ptr<T> InObject, T InbOutOfScopeValue)
: Object(InObject), bOutOfScopeValue(InbOutOfScopeValue) {}
virtual ~FScopedSetter()
{
*Object = bOutOfScopeValue;
}
std::shared_ptr<T> Object;
T bOutOfScopeValue;
};
// Example:
auto bInTaskA = make_shared<bool>(false);
void TaskA()
{
*bInTaskA = true;
FScopedSetter<bool> Setter(bInTaskA, false);
// ..
}你也可以直接使用shared_ptr而不是你的类来检查它是否为空。但是,您的方法允许在bOutOfScopeValue中传递一些额外的信息,从而使其更好。另外,请在上述代码中适当的地方检查NULL。
https://stackoverflow.com/questions/58116225
复制相似问题