【问题标题】:Using C++ shared pointer's aliasing constructor with an empty shared pointer将 C++ 共享指针的别名构造函数与空共享指针一起使用
【发布时间】:2018-02-11 05:43:51
【问题描述】:

std::shared_ptr 有一个别名构造函数,允许新创建的 shared_ptr 在指向其他对象时与现有共享指针共享状态。

我正在考虑滥用这个构造函数来将指针放入 shared_ptr 中的某个全局对象:

int global = 0;

int main() 
{
    // because we point to global object we do not need to track its lifetime
    // so we use empty shared_ptr<void> as a provider of shared state
    std::shared_ptr<int> p(std::shared_ptr<void>(), &global);
    std::shared_ptr<int> pp = p; 
    return *pp;
}

我的问题是:这合法吗?该代码成功地适用于主要编译器。

请注意,我不会问这是否是一件好事。我确实明白有一种规范的方法可以使用无操作删除器将指向全局对象的指针放入 shared_ptr 中。如果它是合法的,这也有点令人不安,因为它可能有可取消引用的 shared_ptr,弱指针总是过期:

    std::shared_ptr<int> p(std::shared_ptr<void>(), &global);
    std::weak_ptr<int> w = p;
    if (p) // p is alive and well 
    {      // and w is not
        *w.lock(); // and here program crashes
    }

【问题讨论】:

    标签: c++ c++11 language-lawyer


    【解决方案1】:

    如您所知,在您当前的解决方案中,puse_count() 为零,这就是weak_ptr 已过期的原因。这似乎没问题,根据 C++ 草案 N4296:

    20.8.2.2.1 shared_ptr 构造函数 [util.smartptr.shared.const]
    模板 shared_ptr(const shared_ptr& r, T* p) noexcept;
    13 效果:构造一个 shared_ptr 实例,该实例存储 p 并与 r 共享所有权。
    14 后置条件:get() == p && use_count() == r.use_count()
    15 [注意:为避免出现悬空指针的可能性,此构造函数的用户必须确保 p 至少在 r 的所有权组被销毁之前仍然有效。 — 结束说明 ]
    16 [ 注意:此构造函数允许创建一个空的 shared_ptr 实例,并存储一个非空值 指针。 ——尾注]

    20.8.2.2.2 shared_ptr 析构函数 [util.smartptr.shared.dest]
    ~shared_ptr();
    1 效果:
    (1.1) — 如果 *this 为空 或与另一个 shared_ptr 实例共享所有权 (use_count() > 1), 没有副作用。
    (1.2) — 否则,如果 *this 拥有一个对象 p 和一个删除器 d,则调用 d(p)。
    (1.3) — 否则,*this 拥有一个指针 p,调用 delete p

    强调我的。
    您可以改用以下内容,它给出了一个 shared_ptr 和一个 use_count()

    std::shared_ptr<int> p(&global, [](int*){});
    

    这使用了一个空的自定义删除器。

    【讨论】:

    • 我确实提到了 no-op 删除器作为解决方案,并且我明白为什么 weak_ptr 已过期。问题是提出的建筑合法。
    • @Григорий Шуренков 我编辑了我的答案以完全回答这个问题。
    • 好吧,正确的答案可能应该包括第 23.11.2.2.1 节 shared_ptr 构造函数 [util.smartptr.shared.const] 明确提到构造函数模板 shared_ptr(const shared_ptr & r, element_type* p) noexcept;可用于创建此类实例:[ 注意:此构造函数允许使用非空存储指针创建一个空的 shared_ptr 实例。 —— 尾注 ]。将其添加到答案中,我会接受。
    • 好的,我加了。
    猜你喜欢
    • 1970-01-01
    • 2016-12-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-27
    • 1970-01-01
    • 2017-08-22
    • 1970-01-01
    相关资源
    最近更新 更多