- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
Flex Ferrum发布代码示例 here (我觉得Minimal, Complete, and Verifiable就够了):
#include <iostream>
#include <functional>
using namespace std;
class Bang
{
public:
Bang(int i = 0) : m_val(i)
{
m_foo = [this] {std::cout << m_val << std::endl;};
}
~Bang()
{
m_val = -1;
}
void Foo()
{
m_foo();
}
private:
int m_val;
std::function<void ()> m_foo;
};
Bang GetBang()
{
return Bang(100500);
}
int main() {
Bang b(100500);
b.Foo();
b = GetBang();
b.Foo();
return 0;
}
我们漂亮的 Flex 还提供 live demo
粗略看了一下,我以为会输出100500
,但真正的输出是:
-1
100500
,而不是-1
)我在提问框
中写了一些我自己的推理,但发现作为答案张贴更合适(会使问题太长)。如果我的回答有误,欢迎指正,欢迎补充
最佳答案
啊,应该归咎于临时的析构函数- Bang(100500)
,返回形式GetBang
,是prvalue
, 并且有 temporary object lifetime
.
class Lambda
{
public:
void operator()() const
{
//output
}
private:
Bang& bang;
public:
Lambda(Bang& bang) : bang{bang}
{
}
} lambda{*this};
...
m_foo = lambda;
因为这里没有RVO
,所以,临时的Bang(100500)
会先赋值给b
,然后被销毁。
自定义 operator()
、constructor
和 destructor
输出一些信息:
#include <iostream>
#include <functional>
using namespace std;
class Bang
{
public:
Bang(int i = 0) : m_val(i)
{
std::cout << "Bang(int i = 0) m_val address is " << &m_val << '\n';
class Lambda
{
public:
void operator()() const
{
std::cout << "operator() m_val address is " << &bang.m_val << '\n';
std::cout << bang.m_val << std::endl;
}
private:
Bang &bang;
public:
Lambda(Bang &bang) : bang{bang}
{
}
} lambda{*this};
m_foo = lambda;
}
~Bang()
{
std::cout << "~Bang()\n";
m_val = -1;
}
void Foo()
{
m_foo();
}
private:
int m_val;
std::function<void()> m_foo;
};
Bang GetBang()
{
return Bang(100500);
}
int main()
{
Bang b;
b = GetBang();
b.Foo();
return 0;
}
输出:
Bang(int i = 0) m_val address is 0x7ffd202c48b0
Bang(int i = 0) m_val address is 0x7ffd202c48e0
~Bang()
operator() m_val address is 0x7ffd202c48e0
-1
~Bang()
显示:
dtor
会在输出之前被调用,这意味着临时对象已经被销毁。 m_value
的地址没有改变。 这两个保证我们仍然可以从 b
的 m_foo()
访问临时的 m_value
。
访问已销毁的对象应该是未定义行为,但不需要警告和错误。
要解决这个问题,有两种方案:
[bang = *this]
。这需要 c++14。[*this]
。这需要 c++17。 live demo
关于c++ - 使用 std::function 作为成员函数,捕获 `this` ,并在析构函数之后从复制的 lambda 访问它,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50773023/
我开始考虑在我 future 的项目或重构中实现控制反转容器,我想知道在正确设计依赖项时哪些原则(除了 GoF 模式)可能需要牢记在心。假设我需要构建一个简单的控制台应用程序,如果它可以访问互联网,它
假设我有一个 RxC contingency table 。这意味着有 R 行和 C 列。我想要一个维度为 RC × (R + C − 2) 的矩阵 X,其中包含行的 R − 1 “主效应”以及列的
我正在尝试使用 DKMS 为正在运行的内核 (4.4) 构 build 备树覆盖。我天真的 Makefile 如下: PWD := $(shell pwd) dtbo-y += my-awsome-o
我有一个 sencha touch 项目。我是用 phonegap 2.9 构建的,并且可以正常工作 device.uuid 返回到设备 ID。当我尝试使用 3.1 device.uuid 构建时抛出
我在安装了 Xcode 4.5.1 的 Mt Lion 上运行。 默认情况下,当我构建并部署到 iOS 5.1 设备时,显示会在我旋转设备时旋转,但当我部署到 iOS 6 模拟器或运行 iOS 的 i
我正在尝试使用 Google Analytics Reporting API v4 构建多折线图。 一张图表,其中我按每天的 session 计数为每个设备(台式机/平板电脑/移动设备)设置了一条线。
我一生都无法使用 xcode 组织者“自动设备配置”中的“团队配置配置文件”在 xcode 4.0.1 中将我的应用程序构建到我的 iPad 上。 该应用程序完美地构建到模拟器,但当我构建到 iPad
我是一名优秀的程序员,十分优秀!