首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >将对象的生存期用作setter的安全性

将对象的生存期用作setter的安全性
EN

Stack Overflow用户
提问于 2019-09-26 19:50:26
回答 2查看 58关注 0票数 2

我做了一个“带作用域的setter”,当变量超出作用域时,它会自动给变量赋值,通常是POD。我主要使用它来跟踪当前是否在某个范围内执行。

代码语言:javascript
运行
复制
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没有使用而决定提前结束它的生命周期?

谢谢!

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-09-26 20:18:19

不要担心,一个命名的setter对象不会在它的作用域结束之前被销毁。它将像往常一样被销毁:按相反的构造顺序。

然而,在发布的代码中有一些小问题。首先,FScopedSetter的析构函数不必是虚的,因为这里没有继承。

并且T::operator=(const T&)决不能抛出(最好声明为noexcept),否则您的作用域赋值器类的析构函数可能会抛出。如果您的代码是针对C++11的,那么将bOutOfScopeValue迁移到*Object会更好

代码语言:javascript
运行
复制
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可能需要同步,这取决于“任务”是否与“线程”有关。

票数 1
EN

Stack Overflow用户

发布于 2019-09-26 20:17:44

一般来说,这个想法似乎很好。但是,最好使用shared_ptr<>来确保依赖对象不会太快超出作用域,因为这会使程序崩溃。

代码语言:javascript
运行
复制
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。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/58116225

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档