zoukankan      html  css  js  c++  java
  • lambda表达式与bind函数

    1. #include<iostream>
    2. #include<algorithm>
    3. #include<sstream>
    4. #include<vector>
    5. #include<cstring>
    6. #include<functional>//bind函数的头文件
    7. //#include <boost/tokenizer.hpp>
    8. usingnamespace std;
    9. usingnamespace placeholders;//_n占位符所要使用的命名空间
    10. /**
    11. * 本程序首先将一个字符串划分成单词存储到容器中去
    12. * 在使用系统提供的算法时,讨论了一元谓词与二元谓词
    13. * 接下来讨论了lambda表达式及其用法
    14. *
    15. * 在很多地方使用同一个函数,一个操作需要很多语句才能完成
    16. * 通常采用使用函数而不是lambda表达式,为了解决一元谓词等的限制,引入标准库bind函数
    17. */
    18. void elimDups(vector<string>& words)
    19. {
    20. sort(words.begin(), words.end());
    21. auto end_unique = unique(words.begin(), words.end());
    22. words.erase(end_unique, words.end());
    23. }
    24. bool compElement(const string & str)
    25. {
    26. return str.length()<5?1:0;
    27. }
    28. void displayVector(vector<string>::iterator beginPos,vector<string>::iterator endPos)
    29. {
    30. while(beginPos != endPos)
    31. {
    32. cout <<*(beginPos++)<< endl;
    33. }
    34. cout << endl;
    35. }
    36. /**< 值捕获 */
    37. void fcn1()
    38. {
    39. size_t v1 =42;
    40. //将v1拷贝到名为f的可调用对象
    41. auto f =[v1]{return v1;};//从lambda类类型生成一个类对象f。在f创建时,使用捕获变量V1给其数据成员v1进行初始化(值拷贝),
    42. v1 =0;
    43. v1 = f();
    44. cout <<"显式捕获--值赋值--"<< v1 << endl;
    45. }
    46. /**< 默认情况下,值捕获是不能改变变量的值,若要改变则需加上mutable关键字 */
    47. void fcn4()
    48. {
    49. size_t v4 =42;
    50. auto f4 =[v4]()mutable
    51. {
    52. return++v4;//观察与fcn1的区别
    53. };
    54. cout <<"mutable--"<< f4()<< endl;
    55. cout <<"mutable--v--"<< v4 << endl;//非引用捕获无法更改捕获变量的值
    56. }
    57. /**< 引用捕获 */
    58. void fcn2()
    59. {
    60. size_t v1 =42;
    61. auto f2 =[&v1]//在f2被创建时,其成员变量v1将引用外部的v1
    62. {
    63. v1 =100;//v1是非const类型,故而能被修改
    64. return v1;
    65. };//构建一个lambda类对象,使用v1给对象的数据成员赋值,此时函数体并未执行
    66. cout << v1 << endl;//42---函数体未执行
    67. cout << f2()<< endl;//100---函数体开始执行
    68. cout <<"显式捕获--引用赋值--"<< v1 << endl;//42---采用的是引用捕获,在函数体被执行时,v1被修改
    69. }
    70. /**< 隐式捕获 */
    71. void fcn3()
    72. {
    73. int v3 =0;
    74. auto f3 =[=]
    75. {
    76. return v3;
    77. };
    78. cout <<"隐式捕获--值赋值--"<< f3()<< endl;
    79. auto f4 =[&]
    80. {
    81. v3 =100;
    82. return v3;
    83. };
    84. cout <<"隐式捕获--引用赋值--"<< f4()<< endl;
    85. cout << v3 << endl;
    86. }
    87. /**
    88. * 混合捕获方式(前边的符号代表隐式捕获的类型,后边的参数列表要与其不同)
    89. * [&,identifier_list] identifier_list采用值捕获方式,identifier_list列表中的各个名字前不能使用&
    90. * 而任何隐式捕获的变量都采用引用方式捕获
    91. * [=,identifier_list] identifier_list采用引用捕获方式,identifier_list列表中的各个名字之前必须使用&
    92. * 而任何隐式捕获的变量都采用引用方式捕获
    93. */
    94. /**< bind函数的实现 */
    95. //先实现要绑定的函数,然后在要使用的地方使用bind函数进行绑定
    96. bool newCompElement(const string & str,constint sz)
    97. {
    98. return str.length()< sz ?1:0;
    99. }
    100. int main()
    101. {
    102. char wordLine[]="The consequences of today are determined by the actions of the past.
    103. To change your future, alter your decisions today.";
    104. vector<string> strVector;
    105. /**
    106. istringstream lineStream(wordLine);//istringsream默认以空格或 或 切割字符串,不能进行设定
    107. while(lineStream>>word)
    108. {
    109. strVector.push_back(word);
    110. }
    111. */
    112. //strtok()
    113. char seps[]=" ,. ";
    114. char* word = strtok(wordLine, seps);
    115. while(word != NULL)
    116. {
    117. strVector.push_back(word);
    118. word = strtok(NULL, seps);
    119. }
    120. for(auto val : strVector)
    121. {
    122. cout << val <<" ";
    123. }
    124. cout << endl;
    125. // elimDups(strVector);
    126. /**< 根据字符串长度是否 < 5,将容器中的字符串重新排列 */
    127. vector<string>::iterator partPos = partition(strVector.begin(), strVector.end(), compElement);
    128. displayVector(partPos, strVector.end());
    129. /**
    130. * 尾置返回类型
    131. * auto func(int i) -> int(*)[10];
    132. * 这是一个函数声明,该函数返回一个指针,该指针指向含有10个int类型的数组
    133. *
    134. * lambda表达式:
    135. * [capture list] (parameter list) -> return type {function body}
    136. * 通常定义一个可调用f,使其等于该lambda表达式
    137. * 例如:auto f = [] {return 42;};
    138. *
    139. * lambda的调用方式与普通函数的调用方式相同,都是使用调用运算符
    140. * cout << f() << endl;//打印42
    141. * lambda表达式可以忽略参数列表和返回类型,但必须包含捕获列表和函数体(内容可以为空)
    142. * 捕获列表只用于局部非static变量,lambda可以直接使用局部static变量和在其函数之外声明的名字
    143. */
    144. size_t sz =5;
    145. auto compSize =[sz](const string & str)->bool
    146. {
    147. return str.length()< sz;
    148. };
    149. partPos = partition(strVector.begin(), strVector.end(), compSize);//这里也可以直接使用lambda表达式替换compSize
    150. displayVector(partPos, strVector.end());
    151. /**< 使用bind函数进行绑定 */
    152. auto newCompEle = bind(newCompElement, _1, sz);
    153. partPos = partition(strVector.begin(),strVector.end(), newCompEle);
    154. //相当于partition(strVector.begin(),strVector.end(), bind(newCompElement, _1, sz));
    155. displayVector(partPos, strVector.end());
    156. /**< 测试lambda的各种捕获 */
    157. fcn1();
    158. fcn2();
    159. fcn3();
    160. fcn4();
    161. return0;
    162. }
    163. /**
    164. * 默认情况下,bind那些不占位符在给bind对象进行赋值时采用的是值拷贝的方式
    165. * 如要要用引用方式传递或绑定对象无法进行拷贝,使用ref来实现引用方式传递
    166. *
    167. * bind(words.begin(),words.end(),bind(print,ref(os),_1,' ');
    168. * ostream &print(ostream &os,const string &s,char c);
    169. *
    170. * 函数ref返回一个对象,包含给定的引用,此对象是可以拷贝的。
    171. * cref函数保存const引用的类
    172. */
     





  • 相关阅读:
    凤凰架构-读书笔记
    《团队协作的五大障碍》笔记
    MongoDB基本操作命令一
    NBI可视化集成clickhouse,实现百亿级数据分析能力
    AI文本与图像数据集荟萃
    gitLab内网部署
    git管理子模块
    git基础使用
    linux内核数据结构之链表-再实现
    win10下安装linux子系统
  • 原文地址:https://www.cnblogs.com/fengkang1008/p/4648371.html
Copyright © 2011-2022 走看看