Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/139.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/opencv/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 为什么unique_ptr为空?_C++_C++11_Move Semantics_Unique Ptr_Object Lifetime - Fatal编程技术网

C++ 为什么unique_ptr为空?

C++ 为什么unique_ptr为空?,c++,c++11,move-semantics,unique-ptr,object-lifetime,C++,C++11,Move Semantics,Unique Ptr,Object Lifetime,在下面的代码段中,foo中的断言始终激发 有人能解释为什么y是nullptr?这看起来像是一个终生问题,即y在调用put和get之间被销毁,但我真的不明白为什么 我错过了什么 短暂性脑缺血发作 Y类 { 公众: Y(常量标准::字符串和名称):m_名称(名称) { } 常量std::string&getName()常量 { 返回m_名称; } 私人: Y(常数Y&); const std::字符串m_name; }; void foo(标准::唯一性) { 如果(y==nullptr) { //

在下面的代码段中,
foo
中的断言始终激发

有人能解释为什么
y
nullptr
?这看起来像是一个终生问题,即
y
在调用
put
get
之间被销毁,但我真的不明白为什么

我错过了什么

短暂性脑缺血发作

Y类
{
公众:
Y(常量标准::字符串和名称):m_名称(名称)
{
}
常量std::string&getName()常量
{
返回m_名称;
}
私人:
Y(常数Y&);
const std::字符串m_name;
};
void foo(标准::唯一性)
{
如果(y==nullptr)
{
//总是开火
断言(false&“nullptr\n”);
}
std::string name=y->getName();
std::cout
void put(std::unique_pty)
{
m_queue.push([&]{foo(std::move(y));});
}

在此函数中,
y
是一个局部变量,当它超出范围时会被销毁。局部变量被捕获(通过引用)由lambda创建的,在执行时不存在-它指向nothing/null/garbage/which,因为
y
已经被销毁。

因为
y
被销毁:

void put(std::unique_ptr<Y> y)
{

    m_queue.push([&] {  // <== capturing y by-reference
        foo(std::move(y)); 
    });

    // <== y gets destroyed here
}
上面的lambda具有类型为
unique\u ptr
的成员变量,因此其复制构造函数被隐式删除。但是[func.wrap.func.con]规定:

模板函数(F);
模板函数(分配器参数、常数A&A、F);
要求:
F
可复制

因此,这也不会编译。这让您有些困惑。

void-put(std::unique\u-pty)
void put(std::unique_ptr<Y> y)
{
    m_queue.push([&] { foo(std::move(y)); });
}
{ m_queue.push([&]{foo(std::move(y));}); }
在这里,您推送一个包含对局部变量
y
的引用的lambda。离开
put
时,局部变量被销毁,lambda包含一个悬空引用。任何进一步的行为都未定义


您需要通过将局部变量移动到lambda中来捕获它,但这是非常高级的,而且还不够,因为
std::function
不能保存仅移动的函数对象。解决这一问题的最简单方法是从
unique\u ptr
切换到
shared\u ptr
并在lambda中按值捕获。

您的问题有两个方面。首先,您通过引用捕获的lambda的生存期(及其副本的生存期)超过了当前本地作用域。请不要这样做。如果您的lambda(及其所有副本)不会被复制出本地作用域的生存期,请仅使用
[&]

简单的答案是,然后执行
[=]
[y]
,但不能复制唯一的指针

在C++14中,您可以执行
[y=std::move(y)]
操作,将
y
移动到lambda捕获中。但是,按值捕获了
唯一的\u ptr
的lambda不能复制。而
std::function
只能存储可调用、可销毁和可复制的对象

解决这一问题的办法是等待只移动
函数
(我认为这已经成为现实——我至少看到了一个非正式的提议),或者自己动手

template<class Sig>
struct unique_function;
namespace details {
  template<class Sig>
  struct i_uf_impl;
  template<class R, class...Args>
  struct i_uf_impl<R(Args...)> {
    virtual ~i_uf_impl() {}
    virtual R invoke(Args&&...) = 0;
  };
  template<class Sig, class F>
  struct uf_impl;
  template<class R, class...Args>
  struct uf_impl<R(Args...):i_uf_impl<R(Args...)>{
    F f;
    virtual R invoke(Args&&...args) override final {
      return f(std::forward<Args>(args)...);
    }
  };
  template<class...Args>
  struct uf_impl<void(Args...):i_uf_impl<void(Args...)>{
    F f;
    virtual void invoke(Args&&...args) override final {
      f(std::forward<Args>(args)...);
    }
  };
}
template<class R, class...Args>
struct unique_function<R(Args...)> {
  std::unique_ptr<details::i_uf_impl<R(Args...)>> pimpl;
  unique_function(unique_function&&)=default;
  unique_function& operator=(unique_function&&)=default;
  unique_function()=default;
  template<class F, class=std::enable_if_t<
    !std::is_same<std::decay_t<F>, unique_function>
    && ( std::is_convertible<std::result_of_t< F(Args...) >, R >{}
      || std::is_same< R, void >{} )
  >>
  unique_function(F&& f):pimpl(
    new details::uf_impl<R(Args...), std::decay_t<F>>{std::forward<F>(f)}
  ) {}
  // override deduction helper:
  unique_function(R(*pfun)(Args...)):pimpl(
    pfun?
      new details::uf_impl<R(Args...), R(*)(Args...)>{pfun}
    : nullptr
  ) {}
  // null case
  unique_function(nullptr_t):unique_function(){}
  explicit bool operator() const { return static_cast<bool>(pimpl); }
  R operator()(Args...args)const{
    return pimpl->invoke( std::forward<Args>(args)... );
  }
};
模板
结构唯一性函数;
命名空间详细信息{
模板
结构i_uf_impl;
模板
结构i_uf_impl{
虚拟~i_uf_impl(){}
虚拟R调用(Args&&…)=0;
};
模板
结构uf_impl;
模板
结构uf_impl>
唯一函数(F&&F):pimpl(
新细节::uf_impl{std::forward(f)}
) {}
//替代扣除帮助程序:
唯一的函数(R(*pfun)(参数…):pimpl(
普芬?
新详细信息::uf_impl{pfun}
:nullptr
) {}
//空格
唯一_函数(nullptr_t):唯一_函数(){}
显式布尔运算符()常量{return static_cast(pimpl);}
R运算符()(Args…Args)常量{
返回pimpl->invoke(std::forward(args)…);
}
};

你的
push()
不应该编译-
函数必须是可复制的。你能解释一下你回答的第二部分吗?也就是说,
std::function
需要复制到你的例子中的相关性。@ksl补充了这个解释。
[p = std::move(y)] {
    foo(std::move(p));
}
template<class F> function(F f);
template <class F, class A> function(allocator_arg_t, const A& a, F f);
void put(std::unique_ptr<Y> y)
{
    m_queue.push([&] { foo(std::move(y)); });
}
template<class Sig>
struct unique_function;
namespace details {
  template<class Sig>
  struct i_uf_impl;
  template<class R, class...Args>
  struct i_uf_impl<R(Args...)> {
    virtual ~i_uf_impl() {}
    virtual R invoke(Args&&...) = 0;
  };
  template<class Sig, class F>
  struct uf_impl;
  template<class R, class...Args>
  struct uf_impl<R(Args...):i_uf_impl<R(Args...)>{
    F f;
    virtual R invoke(Args&&...args) override final {
      return f(std::forward<Args>(args)...);
    }
  };
  template<class...Args>
  struct uf_impl<void(Args...):i_uf_impl<void(Args...)>{
    F f;
    virtual void invoke(Args&&...args) override final {
      f(std::forward<Args>(args)...);
    }
  };
}
template<class R, class...Args>
struct unique_function<R(Args...)> {
  std::unique_ptr<details::i_uf_impl<R(Args...)>> pimpl;
  unique_function(unique_function&&)=default;
  unique_function& operator=(unique_function&&)=default;
  unique_function()=default;
  template<class F, class=std::enable_if_t<
    !std::is_same<std::decay_t<F>, unique_function>
    && ( std::is_convertible<std::result_of_t< F(Args...) >, R >{}
      || std::is_same< R, void >{} )
  >>
  unique_function(F&& f):pimpl(
    new details::uf_impl<R(Args...), std::decay_t<F>>{std::forward<F>(f)}
  ) {}
  // override deduction helper:
  unique_function(R(*pfun)(Args...)):pimpl(
    pfun?
      new details::uf_impl<R(Args...), R(*)(Args...)>{pfun}
    : nullptr
  ) {}
  // null case
  unique_function(nullptr_t):unique_function(){}
  explicit bool operator() const { return static_cast<bool>(pimpl); }
  R operator()(Args...args)const{
    return pimpl->invoke( std::forward<Args>(args)... );
  }
};