QA式语言迁移学习

Posted by
QA式语言迁移学习

QA式语言迁移学习

from Python3 to C++17

本文用Question-Answer这种一问一答的方式,让一个熟悉Python3开发的人,快速上手C++17,找到相同思想在新语言中的最佳实践 ( best practice ),以及新特性下需要避免的写法。

这里我们用Python和C++做个例子,相对熟悉的两种语言。

Q: C++是动态类型,我需要标注每一个变量类型吗?

不一定。使用autodecltype。C++需要每一个变量在编译期有确定的类型(除了void*)。如果编译器在上下文能推断出类型,用auto类型就可以了。

auto a =3;

decltype(e)可以取变量e的类型,用于填写模版或声明变量和函数。

decltype(auto)是C++14新增的类型指示符,可以用来声明变量以及指示函数返回类型。

当decltype(auto)被用于声明变量时,该变量必须立即初始化。假设该变量的初始化表达式为e,那么该变量的类型将被推导为decltype(e)。也就是说在推导变量类型时,先用初始化表达式替换decltype(auto)当中的auto,然后再根据decltype的语法规则来确定变量的类型。

decltype(auto)也可以被用于指示函数的返回值类型。假设函数返回表达式e,那么该函数的返回值类型将被推导为decltype(e)。也就是说在推导函数返回值类型时,先用返回值表达式替换decltype(auto)当中的auto,然后再根据decltype的语法规则来确定函数返回值的类型。

Q: 我需要为每一个类型写一个函数么,重复工作啊!以及,如何判断参数类型以执行分支,像isinstance(obj,class)一样?

Python的变量是一个名字(标识符,identifier),而C++的变量同时有名字和类型。类型是函数签名的一部分,不同的签名是不同的函数。C++的函数重载(Python没有函数重载)和函数模板在编译时批量生成"同名函数",并根据传参类型调用具体的一个;虚函数、继承和dynamic_cast则在运行时选择同名函数。

或者,使用宏,在编译前选择函数或类型。

基于模板和函数重载的:

  • decltype可以取变量的类型,用于填写模版。
  • 模版可以接受类型做为参数,根据实际出现的函数调用,填写"模板"生成一组同名函数。
  • 折叠表达式…可以让模板生成参数量可变的函数。
  • 函数重载(Python没有的特性)允许依据参数类型调用不同函数。模板相当于自动生成的重载函数的机制。

基于继承树的:

  • 基类虚函数。从基类指针调用成员函数时,会根据实际指向的基类或子类值,调用基类或子类的同名函数。
  • dynamic_cast在运行时尝试从基类指针(引用)转化为子类的。有失败的可能。额外的性能代价。

基于宏的:

  • 条件编译:在编译前根据宏替换一些字符串。这样,程序中的变量的实际类型可以变化。比如,int32和int64。

Q: 容器类型在哪里,List, Dict 和Tuple?

C++的STL有容器类(container),配合迭代器(iterator,比Python里的iterator… … 更严肃?)和算法(Algorithm) 使用。以下tuple,string,get,tie,ignore,tuple_element均在命名空间std里,using namespace std;

std::vector

同类元素,数字索引,长度自动增长。

vector<int> vec {1,2,3}; vec.push_back(4);

std::map<T_key,_value>

map<string,int>d { {"a":1}, {"b":2} }; d["c"]=3;

std::tuple<T…>

异类元素,定长。

typdef tuple<int,float,string> MyTuple; MyTuple t {1,1.0,"vvv"}; cout<<get<0>(t);//1 int a; string c; float b = get<float>(t); tuple_element<0,MyTuple>::type b2 = get<1>(t); int tuple_length = tuple_size<MyTuple>::value; // 3

Q: 那么元组拆包呢?用作函数调用?

用tie和ignore做元组拆包

tuple<int,float,string> t {1,1.1,"aaa"}; int a; string c; tie(a,ignore,c) = t;

tuple_cat(t0,t1)拼接元组

forward_as_tuple(T…)组装forward元组

从参数建立一个包含引用的元组。If the arguments are temporaries, forward_as_tuple does not extend their lifetime; they have to be used before the end of the full expression.

尤其用于配合apply函数传参,forward会保留rvalue属性。

apply用元组做参数调用函数

The tuple need not be std::tuple, and instead may be anything that supports std::get and std::tuple_size; in particular, std::array and std::pair may be used.

Q:函数作为变量使用,以及匿名的Lambda函数?开销很大么?

Q:我能定义返回类型不定的函数么?返回值是函数签名的一部分吗?

Leave a Reply