Hello World的正确打zhuang开bi方式———lambda表达式

开始先上一段在C++ Weekly上看到的一段代码。

#include <iostream>
#include <functional>

int main(int argc, char* argv[]) {
    [out = std::ref(std::cout << "Hello ")](){out.get() << "World!\n";}();
    return 0;
}

接下来我们使用如下命令编译这段程序。

g++ hello.cpp -o hello -std=c++14
./hello

你会得到"Hello World!"的输出,然而想要搞懂这段代码,还要从C++11说起。


C++11引入了lambda表达式可以用来创建匿名函数。

// 定义一个匿名函数,但是匿名函数后续无法使用
[](){cout << "hello world!";};

// 定义并使用匿名函数
[](){cout << "hello world!";}(); // "hello world!"

匿名函数体内使用外部变量需要"捕获"。

// 可以得到与上面代码相同的结果
string str = "hello world!";
[str](){cout << str;}(); // "hello world!"

但是通过值捕获的str在匿名函数体内是只读的,你需要使用引用捕获的方式来解决这个问题。

string str = "hello world!";
[&str](){
  str = "hello lambda!";
  cout << str;  // "hello lambda!"
}();  
cout << str;    // "hello lambda"

关于lambda更多的内容我们就不再介绍,这里只铺垫了一些本文需要知道的一些知识。


那么我们现在应该了解了文章开始的那段代码正是通过lambda表达式来实现的,下面我们由浅入深,一步一步来讲解。

// 向cout写入"hello ",并为它创建一个引用
ostream& out = cout << "hello ";  // "hello "

// 值捕获的本质是拷贝构造,但是ios_base的拷贝构造函数是私有的,所以下面这行代码会报错
// error [out](){};

// 我们需要使用引用捕获
[&out](){cout << "world!";}(); // "world!"

上面的程序会输出"hello world!".我们也可以把两行代码并到一行来写。

[&out = cout << "hello "](){cout << "world!";}();

由于lambda capture initializers是C++14标准提供的,所以我们需要使用如下命令编译我们的程序。

g++ hello.cpp -o hello -std=c++14
./hello

C++11中引入了std::ref用于取某个变量的引用,它包含在头文件functional中,所以上面的代码可以改成下面的形式。

[out = ref(cout << "hello ")](){cout << "world!";}();

编译执行,我们可以得到输出"hello world!",需要注意的是,要自己手动编译执行,亲测在dev-cpp中会报错。而这里ref返回的对象相当于ostream&&,我们可以调用ref.get()得到ostream&类型。

[out = ref(cout << "hello ")](){out.get() << "world!";}();

lambda表达式是C++11带来的一颗语法糖(即不通过该形式也可达到同样的效果),但考虑到代码的可读性,在较复杂的一些情况还是不要使用lambda表达式为好。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值