今天看到一篇文章<<C++ 逐渐 Python 化>>, 我个人是认为这个说法是不成立的,但这里面的一些特性对比引起了我的兴趣。
我想尝试下,Go语言所带的一些东西,在C++11中是如何做的,应当很有意思。所以刷刷刷,就有了下面的东西。
目录:
字符串字面值
变量初始化
lambda
值顺序递增
多值赋值及函数返回多值
map查找
可变参数
回调函数
泛型
数组和切片
字面值
这个东西在两种语言中都有比较好的解决方式.Go语言用" ` "符号,C++使用R(" )"这种方式。可以省掉不少转义符的输入。
Golang
- path := `c:\a\b\c\GG再也不用烦转义符了`
- mulln := `"(C++/Golang
- aa'aaa\Cplusplus/gogogo
- author"xiongchuanliang
- `
- fmt.Println(path)
- fmt.Println(mulln)
C++
- string path = R"(c:\a\b\c\GG再也不用烦转义符了)";
- cout << "单行:" << path.c_str() << endl;
-
- string muln = R"(C++/Golang
- aa'aaa\Cplusplus/gogogo
- author"xiongchuanliang
- )";
- cout << "多行:" << muln.c_str() << endl;
变量初始化
现在开发语言的初始化都差不多,都能很方便的定义时初始化,循环也是如下面中的C++ for循环和Go语言中的"for : rang"
形式基本一样。 另外C++的auto,Go语言中的":=",都能省代码的好东西。不过要多提一句,Go语言支持多重赋值,并且变量都
是默认就已初始化好。同时,Go语言也支持指针,但它的指针要安全得多。
Golang
- var k int
- fmt.Println(k)
-
- mArr := []int{ 1, 2, 3}
- var mMap = map[string]int {"a":1,"b":2}
- fmt.Printf("array:%v\nmap:%v \n",mArr,mMap)
-
- i := 10
- pi := &i
- ppi := &pi
- fmt.Println(i,*pi,**ppi)
-
-
-
- 0
- array:[1 2 3]
- map:map[a:1 b:2]
- 10 10 10
C++
- int mArr[] = { 1, 2, 3 };
- auto mList = vector < int > {1, 2, 3, 4};
- auto mMap = map < int, string > {{1, "aa"}, { 2, "bb" }};
-
- cout << "vector: ";
- for (const int& x : mList)
- cout << x << " ";
- cout << endl;
-
- cout << "map: ";
- for (const auto& mp : mMap)
- cout << mp.first << " " << (mp.second).c_str();
- cout << endl;
lambda
lambda这东西在C++11中可是重点推荐的特性,非常的强大。Go语言自然也有,但对于匿名函数中函数外部变量的处理
并没有C++那么多种。 像C++分了四类:
[a,&b] a变量以值的方式呗捕获,b以引用的方式被捕获。
[this] 以值的方式捕获 this 指针。
[&] 以引用的方式捕获所有的外部自动变量。
[=] 以值的方式捕获所有的外部自动变量。
[] 不捕获外部的任何变量。
而Go语言默认就相当于"[=]",即,捕获可见范围内所有的外部变量。
Golang
- mArr := []int{ 1, 2, 3}
- fun := func(i,v int){
- fmt.Printf("idx:%d value:%d \n",i,v)
- }
- for idx,val := range mArr{
- fun(idx,val)
- }
C++
- int arr[] = { 1, 2, 3 };
- for_each(begin(arr), end(arr), [](int n){cout << n << endl; });
-
- auto func = [](int n){cout << n << endl; };
- for_each(begin(arr), end(arr), func);
值顺序递增(iota)
iota这个小东西很有特点,两种语言都支持且都是让数据顺序递增,从功能上看C++的iota似乎更强大灵活些。 但有意思的是,
似乎在Go语言中,iota的使用频率要高得多,被大量的用于像const定义之类的地方,有意思。
Golang
- const (
- Red = iota
- Green
- Blue
- )
- fmt.Println("Red:",Red," Gree:",Green," Blue:",Blue);
C++
- int d[5] = { 0 };
- std::iota(d, d + 5, 10);
-
- cout << "iota_demo(): old : d[5] = { 0 } "<< endl;
- cout << "iota_demo(): iota: d[5] = { ";
- for each (int var in d)
- {
- cout << var <<" ";
- }
- cout <<"} "<< endl;
-
- char e[5] = { 'a' };
- char f[5] = { 0 };
- copy_n(e, 5, f);
-
- cout << "iota_demo(): old : e[5] = { 'a' } " << endl;
- cout << "iota_demo(): iota: e[5] " << endl;
- std::iota(e, e + 5, 'e');
- for (size_t i = 0; i < 5; i++)
- {
- cout <<" iota = " << e[i] << endl;
- }
-
-
- 值顺序递增
- iota_demo(): old : d[5] = { 0 }
- iota_demo(): iota: d[5] = { 10 11 12 13 14 }
- iota_demo(): old : e[5] = { 'a' }
- iota_demo(): iota: e[5]
- iota = e
- iota = f
- iota = g
- iota = h
- iota = i
- 值顺序递增 end.
多值赋值及函数返回多值
这个功能在Go语言中相当方便,C++中则需要使用tuple和 tie等才能实现,有点麻烦,但效果是一样的。
Golang
- func tuple_demo()(int,string){
-
- a,b := 1,2
- fmt.Println("a:",a," b:",b);
-
- c,d := b,a
- fmt.Println("c:",c," d:",d);
-
- return 168, "函数返回的字符串"
- }
C++
- tuple<int, string> tuple_demo(){
- tuple<int, string> ret;
- ret = make_tuple(168, "函数返回的字符串");
- cout << "tuple_demo(): " << get<0>(ret) << " " << (get<1>(ret)).c_str() << endl;
-
- auto triple = make_tuple(5, 6, 7);
- cout << "tuple_demo(): " << get<0>(triple) << " " << get<1>(triple) << " " << get<2>(triple) << endl;
-
- int ti;
- string ts;
- tie(ti, ts) = make_tuple(10, "xcl--将数字和字符赋值给两个变量");
- cout << "tuple_demo(): " << ti << " " << ts.c_str() << endl;
-
- return ret;
- }
-
-
- int ti;
- string ts;
- tie(ti, ts) = tuple_demo();
- cout << "main() <- tuple_demo(): " << ti << " " << ts.c_str() << endl;
-
-
- 多值赋值及函数返回多值
- tuple_demo(): 168 函数返回的字符串
- tuple_demo(): 5 6 7
- tuple_demo(): 10 xcl--将数字和字符赋值给两个变量
- main() <- tuple_demo(): 168 函数返回的字符串
- 多值赋值及函数返回多值 end.
map查找
Go语言中map的查找特别方便. 要找个值,直接map[key]就出来了。C++也可以直接用find(key)的方式,但Go语言直接有个
found的变量,能告知是否有找到,这个要比C++去比end(),要直观些,也可以少打些字。
Golang
- var mMap = map[string]int {"a":1,"b":2,"c":3}
- val,found := mMap["b"]
- if found {
- fmt.Println("found :",val);
- }else{
- fmt.Println("not found");
- }
C++
- typedef map <string, int > map_str_int;
- tuple<string, int, bool> mapfind_demo(map_str_int myMap, string key){
-
- map_str_int::iterator pos;
- pos = myMap.find(key);
- if (pos == myMap.end()){
- return make_tuple("", 0, false);
- }
- else{
- return make_tuple(pos->first, pos->second, true);
- }
- }
-
-
- auto myMap = map_str_int{ { "aa", 1 }, { "bb", 2 }, { "cc", 3 } };
-
- string mpKey;
- int mpValue;
- bool mpFound = false;
- tie(mpKey, mpValue, mpFound) = mapfind_demo(myMap, "bb");
-
- if (mpFound){
- cout << "mapfind_demo: found" << endl;
- }
- else{
- cout << "mapfind_demo: not found" << endl;
- }
可变参数
可变参数是指函数的最后一个参数可以接受任意个参数,我在用Go语言实现的args_demo()例子中,用了效果一样的两种不同
调用方法来展示Go语言对这个下的功夫。然后可以再看看通过C++模板实现的,一个比较有代表性的Print函数来感受感受C++
对这个可变参数的处理方式。
Golang
- func args_demo(first int,args ...int){
- fmt.Println("ars_demo first:",first)
- for _,i := range args {
- fmt.Println("args:",i)
- }
- }
-
-
- args_demo(5,6,7,8);
- mArr := []int{ 5, 6, 7,8}
- args_demo(mArr[0],mArr[1:]...);
-
- fmt.Println("fmtPrintln(): ", 1, 2.0, "C++11", "Golang");
-
- 执行结果
- 变量fmtPrintln(): 1 2 C++11 Golang
- ars_demo first: 5
- args: 6
- args: 7
- args: 8
- ars_demo first: 5
- args: 6
- args: 7
- args: 8
C++
- template<typename T> void fmtPrintln(T value){
- cout << value << endl;
- }
-
- template<typename T, typename... Args>
- void fmtPrintln(T head, Args... args)
- {
- cout << head << " ";
- fmtPrintln(args...);
- }
-
-
- fmtPrintln("fmtPrintln(): ", 1, 2.0, "C++11", "Golang");
-
-
- 变长参数
- fmtPrintln(): 1 2 C++11 Golang
- 变长参数 end.
回调函数
对比看看两种语言函数的回调处理,实现方法没啥差异。
Golang
- type funcType func(string)
-
- func printFunc(str string){
- fmt.Println( "callFunc() -> printFunc():",str)
- }
-
- func callFunc(arg string,f funcType){
- f(arg)
- }
-
- callFunc("回调就是你调我,我调它,大家一起玩。",printFunc)
C++
- void printFunc(string arg){
- cout << "callFunc() -> printFunc():" << arg.c_str() << endl;
- }
-
- typedef void(*callf)(string);
- void callFunc(callf pFunc, string arg){
- pFunc(arg);
- }
- callFunc(printFunc, "回调就是你调我,我调它,大家一起玩。");
泛型
C++泛型就不用多说了,都知道有多强大。Go语言要加入这个不知道是啥时候的事,不过通过简单的反射,还
是可以实现类似的功能,但代码有点长。
Golang
- func compare(v1, v2 interface{}) (int, error) {
-
- switch v1.(type) {
- case int:
- if v1.(int) < v2.(int) {
- return -1, nil
- } else if v1.(int) == v2.(int) {
- return 0, nil
- }
- case int8:
- if v1.(int8) < v2.(int8) {
- return -1, nil
- } else if v1.(int8) == v2.(int8) {
- return 0, nil
- }
- case int32:
- if v1.(int32) < v2.(int32) {
- return -1, nil
- } else if v1.(int32) == v2.(int32) {
- return 0, nil
- }
-
-
-
- default:
- return -2, errors.New("未能处理的数据类型.")
- }
- return 1, nil
- }
-
-
- v1 := 13
- v2 := 53
- ret, err := compare(v1, v2)
- if err != nil {
- fmt.Println(err)
- return
- }
- switch ret {
- case -1:
- fmt.Println("v1 < v2")
- case 0:
- fmt.Println("v1 == v2")
- case 1:
- fmt.Println("v1 > v2")
- default:
- fmt.Println("defualt")
- }
C++
- template <typename T> int compare(const T v1, const T v2){
- if (v1 < v2){
- cout << "compare(): v1 < v2" << endl;
- return -1;
- }
- else if (v1 == v2){
- cout << "compare(): v1 == v2" << endl;
- return 0;
- }
- else{
- cout << "compare(): v1 > v2" << endl;
- return 1;
- }
- }
-
-
- int i1 = 5, i2 = 7;
- double d1 = 52.5, d2 = 10.7;
- compare(i1, i2);
- compare(d1, d2);
数组和切片(sclie)
数组/切片Go语言做得非常灵活,不一一举例,这里主要可以看看C++的。我用copy_n,copy_if 模拟二下简单的切片功能。
Golang
- a := [5]int{ 1, 2, 3, 4, 5 }
- b := a[:3]
- c := a[1:2]
- fmt.Println(a)
- fmt.Println(b)
- fmt.Println(c)
-
-
- [1 2 3 4 5]
- [1 2 3]
- [2]
C++
- int a[5] = { 1, 2, 3, 4, 5 };
- int b[3] = { 0 };
- int c[2] = { 0 };
-
-
- cout << "a[5] = { 1, 2, 3, 4, 5 }" << endl;
- cout << "array[:end_pos]: b = array[:3]" << endl;
-
- copy_n(a, 3, b);
- for each (int var in b)
- {
- cout << " " << var;
- }
- cout << endl;
-
-
- cout << "a[5] = { 1, 2, 3, 4, 5 }" << endl;
- cout << "array[begin_pos:end_pos]: c = array[1,2] " << endl;
-
- int begin_pos = 1;
- int subLen = sizeof(c) / sizeof(c[0]);
- int end_pos = begin_pos + subLen;
- copy_if(a + begin_pos, a + end_pos, c, [](int v){return true; });
-
- for each (int var in c)
- {
- cout << " " << var ;
- }
- cout << endl;
-
-
- 数组和切片(sclie)
- a[5] = { 1, 2, 3, 4, 5 }
- array[:end_pos]: b = array[:3]
- 1 2 3
- a[5] = { 1, 2, 3, 4, 5 }
- array[begin_pos:end_pos]: c = array[1,2]
- 2 3
- 数组和切片(sclie) end.
很粗浅的分别实现下这几个点,体会是C++很强大,Golang更纯粹,少即是多。
Go语言和C++完整测试源码我放在此: 点击下载
可以自行下载编译。