我想了解一些关于如何正确思考C++ 11闭包以及std::function如何实现它们以及如何处理内存的信息.
虽然我不相信过早优化,但我确实习惯在编写新代码时仔细考虑我的选择对性能的影响.我还进行了大量的实时编程,例如微控制器和音频系统,其中要避免非确定性的存储器分配/解除分配暂停.
因此,我想更好地了解何时使用或不使用C++ lambdas.
我目前的理解是没有捕获闭包的lambda就像一个C回调.但是,当通过值或引用捕获环境时,将在堆栈上创建匿名对象.当必须从函数返回值闭包时,将其包装进去std::function.在这种情况下闭包内存会发生什么?它是从堆栈复制到堆?它是否在被释放时std::function被释放,即它是否被引用计数为std::shared_ptr?
我想在实时系统中我可以建立一个lambda函数链,将B作为一个连续参数传递给A,以便A->B创建一个处理管道.在这种情况下,A和B闭包将被分配一次.虽然我不确定这些是否会在堆栈或堆上分配.然而,一般来说,这在实时系统中使用似乎是安全的.另一方面,如果B构造一些它返回的lambda函数C,那么C的内存将被重复分配和释放,这对于实时使用是不可接受的.
在伪代码中,一个DSP循环,我认为这将是实时安全的.我想执行处理块A然后执行B,其中A调用它的参数.这两个函数都返回std::function对象,因此f它将是一个std::function对象,其环境存储在堆上:
auto f = A(B); // A returns a function which calls B
// Memory for the function returned by A is on the heap?
// Note that A and B may maintain a state
// via mutable value-closure!
for (t=0; t<1000; t++) {
y = f(t)
}
Run Code Online (Sandbox Code Playgroud)
我认为在实时代码中使用它可能很糟糕:
for (t=0; t<1000; t++) {
y = A(B)(t); …Run Code Online (Sandbox Code Playgroud) 一些C++编译器允许匿名联合和结构作为标准C++的扩展.这有点语法糖,偶尔会非常有帮助.
阻止它成为标准一部分的理由是什么?是否存在技术障碍?一个哲学的?或者仅仅是不足以证明它的合理性?
这是我正在谈论的样本:
struct vector3 {
union {
struct {
float x;
float y;
float z;
};
float v[3];
};
};
Run Code Online (Sandbox Code Playgroud)
我的编译器会接受这个,但它警告"无名结构/联合"是C++的非标准扩展.
在使用C++ 11和Boost.Asio的应用程序中,我开始使用lambda函数和一个std::unique_ptr.我想将此unique_ptr的所有权转移到lambda.您无法通过值捕获unique_ptr,因为此类不提供复制构造函数.通过引用捕获它也是愚蠢的,因为我确实希望转让所有权.
我决定用它std::bind来传递unique_ptr这个lambda函数的最后一个参数.我std::move用来给这个lambda提供一个r值引用.稍后我会将这个r值移动到std::unique_ptr(lambda的本地).我遇到了一些可怕的gcc错误,并且想知道我在代码中错过了什么.
这是包含我丑陋的非工作技巧的代码:
void NetworkClient::start()
{
// Avoid the naggle algorithm on packets.
ip::tcp::no_delay optionNoDelay(true);
socket_.set_option(optionNoDelay);
// Lambda function that receive a packet header.
std::function<void (const boost::system::error_code& error, std::size_t bytesTransfered)> receiveHeaderHandler =
[this, &receiveHeaderHandler] (const boost::system::error_code& error, std::size_t bytesTransfered)
{
if (error)
{
std::cout << LogType::ERROR << "Error while receiving a packet header" << std::endl;
}
if (bytesTransfered < 6)
{
std::cout << LogType::ERROR << …Run Code Online (Sandbox Code Playgroud)