【问题标题】:Is the behavior of a functor created by std::bind well-defined when the bound object expires?当绑定对象过期时,std::bind 创建的仿函数的行为是否明确?
【发布时间】:2016-05-03 09:53:25
【问题描述】:

以下代码的行为是否定义良好? f() 调用的行为如何?

#include <functional>
#include <iostream>

struct A
{
  void shout()
  {
      std::cout <<"shout";
  }
};


int main()
{
    std::function<void()> f;
    {
        A a;
        f = std::bind(&A::shout, &a);
    }

    f();  // what happens here?
}

【问题讨论】:

    标签: c++ language-lawyer stdbind


    【解决方案1】:

    您的代码最终会在函数包装器中存储一个悬空引用(指向不再存在的对象),并且调用该函数会导致未定义的行为。

    如果原始对象的寿命不如包装器,您始终可以在包装器中存储对象的副本

    f = std::bind(&A::shout, a);
    //                      ^^^ copy
    

    【讨论】:

      【解决方案2】:

      为了表明这是未定义的,请注意存储的地址变为无效的指针值 - [basic.stc]/3

      当一个存储区域的持续时间结束时, 所有指针的值表示的任何部分的地址 释放的存储成为无效的指针值([basic.compound])。

      在对绑定函子的调用中,该指针被取消引用以执行成员函数调用,其中[basic.stc.dynamic.deallocation]/4 适用:

      通过一个无效的指针值间接传递一个无效的 指向释放函数的指针值具有未定义的行为。

      相反,您可以为每个值绑定a(省略与号)。

      【讨论】:

      • 另外,对成员函数的调用需要一个对象,[class.mfct.non-static]p1。请注意,如果 shout 是静态的,则代码没有 UB AFAIK。 (存在 when*/*if 间接发生的潜在问题。)
      • @dyp 编辑:哎呀,我以为你指的是 /2。
      • p2 有 DR 吗?
      • @dyp 间接发生,这会导致未定义的行为。我们可以像使用空指针一样放松,允许丢弃间接的值,但这不是我们想要的。
      • @dyp /2 没有缺陷,因为它不一致,但它应该涵盖传递无效左值的情况。 (与其说是缺陷,不如说是需要澄清。/1 对所需要的对象不够明确。)
      猜你喜欢
      • 2015-07-14
      • 2020-05-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多