#include <iostream>
#include <functional>
// Testing class - just to see constructing/destructing.
class T {
private:
static int idCounter; // The global counter of the constructed objects of this type.
public:
const int id; // Unique object ID
inline T() : id(++idCounter) {
std::cout << " Constuctor Id=" << id << std::endl;
};
inline T(const T& src) : id(++idCounter) {
std::cout << " Copy constructor Id=" << id << std::endl;
}
inline T(const T&& src) : id(++idCounter) {
std::cout << " Move constructor Id=" << id << std::endl;
}
inline void print() const {
std::cout << " Print is called for object with id=" << id << std::endl;
}
inline ~T() {
std::cout << " Destructor Id=" << id << std::endl;
}
};
int T::idCounter=0;
// Declare type of the std::function to store our lambda.
typedef std::function<int (void)> Callback;
int main()
{
std::cout << "Let's the game begin!" << std::endl;
T obj; // Custruct the first object.
std::cout << "Let's create a pointer to the lambda." << std::endl;
// Make a labmda with captured object. (The labmda prints and returns object's id).
// It should make one (local) copy of the captured object but it makes it twice - why?!
const Callback* pcb= new Callback( [obj]() -> int {
obj.print();
return obj.id;
} );
std::cout << "Now let's print lambda execution result." << std::endl;
std::cout << "The functor's id is " << (*pcb)() << std::endl;
std::cout << "Destroying the lambda." << std::endl;
delete pcb;
std::cout << "Terminating." << std::endl;
return 0;
}
输出为:
Let's the game begin! Constuctor Id=1 Let's create a pointer to the lambda. Copy constructor Id=2 Move constructor Id=3 Destructor Id=2 Now let's print lambda execution result. Print is called for object with id=3 The functor's id is 3 Destroying the lambda. Destructor Id=3 Terminating. Destructor Id=1
我用带有捕获对象lambda创建了一个std:function。它应该为lambda创建对象的本地副本,但它创建了两次副本(看看move constructor call-用粗体突出显示)。实际上,它会复制整个lambda对象。为什么?我怎么才能避免呢?我正在使用lambdas进行线程间事件处理,它们可能会捕获大量的日期,所以我试图找到一种方法来避免不必要的复制。因此,任务很简单--以最小的开销将构造的lambda传递到函数中--如果它将为每个构造的lambda复制两次数据,我将寻找另一种处理事件的方法。
我使用的是GCCV4.7.2强制到GNU C++11。
好吧,输出很混乱,因为编译器执行了一个copy-elision。因此,为了理解这种行为,我们需要暂时禁用copy-elision。编译代码时使用-fno-elide-constructors
标志:
$ g++ -std=c++11 -fno-elide-constructors main.cpp
现在它给出了这个输出(demo-withon-copy-elision):
Let's create a pointer to the lambda.
Copy constructor Id=2
Move constructor Id=3
Move constructor Id=4
Destructor Id=3
Destructor Id=2
嗯,这是意料之中的。复制是在创建lambda时完成的:
[obj]() -> int {
//^^^^ COPY!
obj.print();
return obj.id;
}
第一个移动是在将lambda传递给std::function
的构造函数时完成的,因为lambda是一个rvalue,因此调用move-constructor。请注意,-fno-elide-constructors
还禁用了move-elision(毕竟这只是copy的一个更快的版本!)。
第二步是在写入构造函数初始化列表中的std::function
的成员数据时完成的。
到目前为止还不错。
现在,如果删除-fno-elide-constructors
,编译器将优化第一个移动(因此它不调用移动构造函数),这就是为什么输出如下:
Let's create a pointer to the lambda.
Copy constructor Id=2
Move constructor Id=3
Destructor Id=2
请参阅demo-with-copy-elision。
您现在看到的移动是因为将-the-lambda移动到std::function
的成员数据中。你不能回避这一步。
还要注意,复制/移动lambda也会导致复制/移动捕获的数据(即递归复制/移动)。
无论如何,如果您担心复制捕获的对象(假设它是一个巨大的对象),那么我建议您使用new
创建捕获的对象,这样复制捕获的对象就意味着复制一个指针(4或8字节!)。那应该很管用!
希望能有所帮助。
建议将以下语句更改为NetBeans中的lambda表达式。 但是,当我应用假定的更改(Alt Enter)时,我得到了: 当这不会与消息一起编译时: 没有找到合适的构造函数为KeyFrame(持续时间,(事件前夕[…]}}})-参数不匹配 问题是为什么NetBeans会提出一些它无法实现的东西?如何在Timeline构造函数中实际使用lambda函数?谢谢
假设我们有我的代码的简化版本: 我试图将lambda函数作为参数传递给函数,但只有当我将lambda显式分配给特定的类型时,它才起作用。这是可行的: 上面的例子是可行的,但我想实现下面的例子,因为审美的原因,不知道这是否可能: 我唯一的要求是应该接受带有模板化返回类型的lambda和函数,以及带有特定类型的输入参数,例如。
我有一个场景,需要使用AWS CDK python语言创建多个lambda函数。 当我尝试为每个函数创建多个堆栈时,它创建了第一个函数和显示该函数已经存在的其余函数。 如果我们调试cdk。对于创建的模板,两个堆栈Lambda函数显示相同的资源ID,如下所示: 如何为创建多个函数的资源获取唯一ID?你能建议如何克服这个问题吗?我想创建多个lambda函数,即使解决方案是通过创建循环来实现的,也很好
我试图用Lamdas简化我的对象创建。 如下所示:
为什么在添加捕获元素时,下面的lambda不符合签名? 但这会吗? 签名:
KeyError:我使用的“记录”Lambd@Edge使用CloudFront请求原件。我可以成功通过测试。但是,在cloudwatch中,我看到了错误: 根据文件记录,“记录”应出现在事件中。https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/lambda-event-structure.html