Golang部份特性的C++对比实现

今天看到一篇文章<<C++ 逐渐 Python 化>>, 我个人是认为这个说法是不成立的,但这里面的一些特性对比引起了我的兴趣。

我想尝试下,Go语言所带的一些东西,在C++11中是如何做的,应当很有意思。所以刷刷刷,就有了下面的东西。

           目录:

                     字符串字面值
                     变量初始化
                     lambda
                     值顺序递增
                     多值赋值及函数返回多值
                     map查找
                     可变参数
                     回调函数
                     泛型
                     数组和切片


字面值

          这个东西在两种语言中都有比较好的解决方式.Go语言用" ` "符号,C++使用R(" )"这种方式。可以省掉不少转义符的输入。

Golang 

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. path := `c:\a\b\c\GG再也不用烦转义符了`  
  2. mulln := `"(C++/Golang  
  3.      aa'aaa\Cplusplus/gogogo  
  4.      author"xiongchuanliang  
  5.     `     
  6. fmt.Println(path)  
  7. fmt.Println(mulln)  
C++ 

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. string path = R"(c:\a\b\c\GG再也不用烦转义符了)";  
  2.     cout << "单行:" << path.c_str() << endl;  
  3.   
  4.     string muln = R"(C++/Golang  
  5.      aa'aaa\Cplusplus/gogogo  
  6.      author"xiongchuanliang  
  7.     )";  
  8.     cout << "多行:" << muln.c_str() << endl;  

  

变量初始化

       现在开发语言的初始化都差不多,都能很方便的定义时初始化,循环也是如下面中的C++ for循环和Go语言中的"for : rang"

形式基本一样。 另外C++的auto,Go语言中的":=",都能省代码的好东西。不过要多提一句,Go语言支持多重赋值,并且变量都

是默认就已初始化好。同时,Go语言也支持指针,但它的指针要安全得多。吐舌头

Golang      

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. var k int  
  2. fmt.Println(k)  
  3.   
  4. mArr := []int{ 1, 2, 3}  
  5. var mMap = map[string]int {"a":1,"b":2}  
  6. fmt.Printf("array:%v\nmap:%v \n",mArr,mMap)  
  7.   
  8. i := 10    
  9. pi := &i  //*i  
  10. ppi := &pi  //**int  
  11. fmt.Println(i,*pi,**ppi)  
  12.   
  13.   
  14. //结果:  
  15. 0  
  16. array:[1 2 3]  
  17. map:map[a:1 b:2]  
  18. 10 10 10  

 C++   

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. int mArr[] = { 1, 2, 3 };  
  2.     auto mList = vector < int > {1, 2, 3, 4};  
  3.     auto mMap = map < int, string > {{1, "aa"}, { 2, "bb" }};  
  4.   
  5.     cout << "vector: ";  
  6.     for (const int& x : mList)  
  7.         cout << x << " ";  
  8.     cout << endl;  
  9.   
  10.     cout << "map: ";  
  11.     for (const auto& mp : mMap)  
  12.         cout << mp.first << " " << (mp.second).c_str();  
  13.     cout << endl;  

lambda

      lambda这东西在C++11中可是重点推荐的特性,非常的强大。Go语言自然也有,但对于匿名函数中函数外部变量的处理

并没有C++那么多种。 像C++分了四类:

         [a,&b] a变量以值的方式呗捕获,b以引用的方式被捕获。
         [this] 以值的方式捕获 this 指针。
         [&] 以引用的方式捕获所有的外部自动变量。
         [=] 以值的方式捕获所有的外部自动变量。
         [] 不捕获外部的任何变量。

  而Go语言默认就相当于"[=]",即,捕获可见范围内所有的外部变量。

Golang     

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. mArr := []int{ 1, 2, 3}  
  2.     fun := func(i,v int){  
  3.         fmt.Printf("idx:%d value:%d \n",i,v)  
  4.     }  
  5.     for idx,val := range mArr{  
  6.         fun(idx,val)  
  7.     }  

 C++    

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. int arr[] = { 1, 2, 3 };  
  2.     for_each(begin(arr), end(arr), [](int n){cout << n << endl; });  
  3.   
  4.     auto func = [](int n){cout << n << endl; };  
  5.     for_each(begin(arr), end(arr), func);  

值顺序递增(iota)

     iota这个小东西很有特点,两种语言都支持且都是让数据顺序递增,从功能上看C++的iota似乎更强大灵活些。 但有意思的是,

似乎在Go语言中,iota的使用频率要高得多,被大量的用于像const定义之类的地方,有意思。

Golang       

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. const (  
  2.         Red = iota  
  3.         Green  
  4.         Blue  
  5.     )  
  6.     fmt.Println("Red:",Red," Gree:",Green," Blue:",Blue);  

C++     

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. int d[5] = { 0 };  
  2. std::iota(d, d + 5, 10);  
  3.   
  4. cout << "iota_demo(): old : d[5] = { 0 } "<< endl;  
  5. cout << "iota_demo(): iota: d[5] = { ";  
  6. for each (int var in d)  
  7. {  
  8.     cout <<  var <<" ";  
  9. }  
  10. cout <<"} "<< endl;  
  11.   
  12. char e[5] = { 'a' };  
  13. char f[5] = { 0 };  
  14. copy_n(e, 5, f);  
  15.   
  16. cout << "iota_demo(): old : e[5] = { 'a' } " << endl;  
  17. cout << "iota_demo(): iota: e[5]  " << endl;  
  18. std::iota(e, e + 5, 'e');  
  19. for (size_t i = 0; i < 5; i++)  
  20. {  
  21.     cout <<" iota = " << e[i] << endl;  
  22. }  
  23.   
  24. //结果:  
  25. 值顺序递增  
  26. iota_demo(): old : d[5] = { 0 }  
  27. iota_demo(): iota: d[5] = { 10 11 12 13 14 }  
  28. iota_demo(): old : e[5] = { 'a' }  
  29. iota_demo(): iota: e[5]  
  30.  iota = e  
  31.  iota = f  
  32.  iota = g  
  33.  iota = h  
  34.  iota = i  
  35. 值顺序递增 end.  

多值赋值及函数返回多值

     这个功能在Go语言中相当方便,C++中则需要使用tuple和 tie等才能实现,有点麻烦,但效果是一样的。

Golang         

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. func tuple_demo()(int,string){  
  2.   
  3.     a,b := 1,2  
  4.     fmt.Println("a:",a," b:",b);  
  5.   
  6.     c,d := b,a  
  7.     fmt.Println("c:",c," d:",d);  
  8.   
  9.     return 168, "函数返回的字符串"  
  10. }  
 C++               
[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. tuple<int, string> tuple_demo(){  
  2.     tuple<int, string> ret;  
  3.     ret = make_tuple(168, "函数返回的字符串");  
  4.     cout << "tuple_demo(): " << get<0>(ret) << " " << (get<1>(ret)).c_str() << endl;  
  5.   
  6.     auto triple = make_tuple(5, 6, 7);  
  7.     cout << "tuple_demo(): " << get<0>(triple) << " " << get<1>(triple) << " " << get<2>(triple) << endl;  
  8.   
  9.     int ti;  
  10.     string ts;  
  11.     tie(ti, ts) = make_tuple(10, "xcl--将数字和字符赋值给两个变量");  
  12.     cout << "tuple_demo(): " << ti << " " << ts.c_str() << endl;  
  13.   
  14.     return ret;  
  15. }  
  16.   
  17. //调用:  
  18. int ti;  
  19. string ts;  
  20. tie(ti, ts) = tuple_demo();  
  21. cout << "main() <- tuple_demo(): " << ti << " " << ts.c_str() << endl;  
  22.   
  23. //结果:  
  24. 多值赋值及函数返回多值  
  25. tuple_demo(): 168 函数返回的字符串  
  26. tuple_demo(): 5 6 7  
  27. tuple_demo(): 10 xcl--将数字和字符赋值给两个变量  
  28. main() <- tuple_demo(): 168 函数返回的字符串  
  29. 多值赋值及函数返回多值 end.  

map查找

       Go语言中map的查找特别方便. 要找个值,直接map[key]就出来了。C++也可以直接用find(key)的方式,但Go语言直接有个

found的变量,能告知是否有找到,这个要比C++去比end(),要直观些,也可以少打些字。

Golang         

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. var mMap = map[string]int {"a":1,"b":2,"c":3}  
  2.     val,found := mMap["b"]  
  3.     if found {  
  4.         fmt.Println("found :",val);  
  5.     }else{  
  6.         fmt.Println("not found");  
  7.     }  

C++    

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. typedef map <string, int > map_str_int;  
  2. tuple<string, intbool> mapfind_demo(map_str_int myMap, string key){  
  3.       
  4.     map_str_int::iterator pos;    
  5.     pos = myMap.find(key);  
  6.     if (pos == myMap.end()){  
  7.         return make_tuple("", 0, false);  
  8.     }  
  9.     else{  
  10.         return make_tuple(pos->first, pos->second, true);  
  11.     }  
  12. }  
  13.   
  14. //调用:  
  15. auto myMap = map_str_int{ { "aa", 1 }, { "bb", 2 }, { "cc", 3 } };  
  16.   
  17. string mpKey;  
  18. int mpValue;  
  19. bool  mpFound = false;  
  20. tie(mpKey, mpValue, mpFound) = mapfind_demo(myMap, "bb");  
  21.   
  22. if (mpFound){  
  23.     cout << "mapfind_demo: found" << endl;  
  24. }  
  25. else{  
  26.     cout << "mapfind_demo: not found" << endl;  
  27. }  

可变参数

     可变参数是指函数的最后一个参数可以接受任意个参数,我在用Go语言实现的args_demo()例子中,用了效果一样的两种不同

调用方法来展示Go语言对这个下的功夫。然后可以再看看通过C++模板实现的,一个比较有代表性的Print函数来感受感受C++

对这个可变参数的处理方式。

Golang         

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. func args_demo(first int,args ...int){  
  2.     fmt.Println("ars_demo first:",first)  
  3.     for _,i := range args {  
  4.         fmt.Println("args:",i)  
  5.     }  
  6. }  
  7.   
  8. //调用  
  9. args_demo(5,6,7,8);  
  10. mArr := []int{ 5, 6, 7,8}  
  11. args_demo(mArr[0],mArr[1:]...);  
  12.   
  13. fmt.Println("fmtPrintln(): ", 1, 2.0, "C++11""Golang");  
  14.   
  15. 执行结果  
  16. 变量fmtPrintln():  1 2 C++11 Golang  
  17. ars_demo first: 5  
  18. args: 6  
  19. args: 7  
  20. args: 8  
  21. ars_demo first: 5  
  22. args: 6  
  23. args: 7  
  24. args: 8  

C++     

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. template<typename T> void fmtPrintln(T value){  
  2.     cout << value << endl;  
  3. }  
  4.   
  5. template<typename T, typename... Args>  
  6. void fmtPrintln(T head, Args... args)  
  7. {  
  8.     cout << head << " ";  
  9.     fmtPrintln(args...);  
  10. }  
  11.   
  12. //调用  
  13. fmtPrintln("fmtPrintln(): ", 1, 2.0, "C++11""Golang");  
  14.   
  15. //执行结果:  
  16. 变长参数  
  17. fmtPrintln():  1 2 C++11 Golang  
  18. 变长参数 end.  

回调函数

       对比看看两种语言函数的回调处理,实现方法没啥差异。

Golang          

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. type funcType func(string)  
  2.   
  3. func printFunc(str string){  
  4.     fmt.Println( "callFunc() -> printFunc():",str)  
  5. }  
  6.   
  7. func callFunc(arg string,f funcType){  
  8.     f(arg)  
  9. }  
  10.   
  11. callFunc("回调就是你调我,我调它,大家一起玩。",printFunc)  


C++       

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. void printFunc(string arg){  
  2.     cout << "callFunc() -> printFunc():" << arg.c_str() << endl;  
  3. }  
  4.   
  5. typedef void(*callf)(string);  
  6. void callFunc(callf pFunc, string arg){ //void(*pFunc)(string)  
  7.     pFunc(arg);  
  8. }  
  9. callFunc(printFunc, "回调就是你调我,我调它,大家一起玩。");  


泛型

        C++泛型就不用多说了,都知道有多强大。Go语言要加入这个不知道是啥时候的事,不过通过简单的反射,还

是可以实现类似的功能,但代码有点长。

Golang

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. func compare(v1, v2 interface{}) (int, error) {  
  2.   
  3.     switch v1.(type) {  
  4.     case int:  
  5.         if v1.(int) < v2.(int) {  
  6.             return -1, nil  
  7.         } else if v1.(int) == v2.(int) {  
  8.             return 0, nil  
  9.         }  
  10.     case int8:  
  11.         if v1.(int8) < v2.(int8) {  
  12.             return -1, nil  
  13.         } else if v1.(int8) == v2.(int8) {  
  14.             return 0, nil  
  15.         }  
  16.     case int32:  
  17.         if v1.(int32) < v2.(int32) {  
  18.             return -1, nil  
  19.         } else if v1.(int32) == v2.(int32) {  
  20.             return 0, nil  
  21.         }  
  22.   
  23.     //省略......  
  24.   
  25.     default:  
  26.         return -2, errors.New("未能处理的数据类型.")  
  27.     }  
  28.     return 1, nil  
  29. }  
  30.   
  31. //调用:  
  32. v1 := 13  
  33. v2 := 53  
  34. ret, err := compare(v1, v2)  
  35. if err != nil {  
  36.     fmt.Println(err)  
  37.     return  
  38. }  
  39. switch ret {  
  40. case -1:  
  41.     fmt.Println("v1 < v2")  
  42. case 0:  
  43.     fmt.Println("v1 == v2")  
  44. case 1:  
  45.     fmt.Println("v1 > v2")  
  46. default:  
  47.     fmt.Println("defualt")  
  48. }  

C++         

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. template <typename T> int compare(const T v1, const T v2){  
  2.     if (v1 < v2){  
  3.         cout << "compare(): v1 < v2" << endl;  
  4.         return -1;  
  5.     }  
  6.     else if (v1 == v2){  
  7.         cout << "compare(): v1 == v2" << endl;  
  8.         return 0;  
  9.     }  
  10.     else{  
  11.         cout << "compare(): v1 > v2" << endl;  
  12.         return 1;  
  13.     }  
  14. }  
  15.   
  16. //调用:  
  17. int i1 = 5, i2 = 7;  
  18. double d1 = 52.5, d2 = 10.7;  
  19. compare(i1, i2);  
  20. compare(d1, d2);  


数组和切片(sclie)

     数组/切片Go语言做得非常灵活,不一一举例,这里主要可以看看C++的。我用copy_n,copy_if 模拟二下简单的切片功能。

Golang

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1.     a := [5]int{ 1, 2, 3, 4, 5 }  
  2.     b := a[:3]  
  3.     c := a[1:2]  
  4.     fmt.Println(a)  
  5.     fmt.Println(b)  
  6.     fmt.Println(c)  
  7.       
  8. //运行结果:<span style="white-space:pre"> </span>  
  9. [1 2 3 4 5]  
  10. [1 2 3]  
  11. [2]  

C++    

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1.     int a[5] = { 1, 2, 3, 4, 5 };  
  2.     int b[3] = { 0 };  
  3.     int c[2] = { 0 };  
  4.   
  5.   
  6.     cout << "a[5] = { 1, 2, 3, 4, 5 }" << endl;  
  7.     cout << "array[:end_pos]: b = array[:3]" << endl;  
  8.     // array[:end_pos]  
  9.     copy_n(a, 3, b);  
  10.     for each (int var in b)  
  11.     {  
  12.         cout << " " << var;  
  13.     }  
  14.     cout << endl;  
  15.   
  16.   
  17.     cout << "a[5] = { 1, 2, 3, 4, 5 }" << endl;  
  18.     cout << "array[begin_pos:end_pos]: c = array[1,2] " << endl;  
  19.     // array[begin_pos:end_pos]  
  20.     int begin_pos = 1;  
  21.     int subLen = sizeof(c) / sizeof(c[0]);  
  22.     int end_pos = begin_pos + subLen;  
  23.     copy_if(a + begin_pos, a + end_pos, c, [](int v){return true; });  
  24.       
  25.     for each (int var in c)  
  26.     {  
  27.         cout << " " << var ;  
  28.     }  
  29.     cout << endl;  
  30.   
  31. //运行结果:   
  32. 数组和切片(sclie)  
  33. a[5] = { 1, 2, 3, 4, 5 }  
  34. array[:end_pos]: b = array[:3]  
  35.  1 2 3  
  36. a[5] = { 1, 2, 3, 4, 5 }  
  37. array[begin_pos:end_pos]: c = array[1,2]  
  38.  2 3  
  39. 数组和切片(sclie) end.  

       很粗浅的分别实现下这几个点,体会是C++很强大,Golang更纯粹,少即是多。

      Go语言和C++完整测试源码我放在此: 点击下载 

       可以自行下载编译。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值