当前位置: 首页 > news >正文

温州网站建设 温州网站制作软件网站建设

温州网站建设 温州网站制作,软件网站建设,深圳歌剧院设计方案,北京公司摇号目录 一、constexpr 关键字 1.1 - constexpr 修饰普通变量 1.2 - constexpr 修饰函数 1.3 - constexpr 修饰类的构造函数 1.4 - constexpr 和 const 的区别 二、decltype 关键字 2.1 - 推导规则 2.2 - 实际应用 一、constexpr 关键字 constexpr 是 C11 新引入的关键字…目录 一、constexpr 关键字 1.1 - constexpr 修饰普通变量 1.2 - constexpr 修饰函数 1.3 - constexpr 修饰类的构造函数 1.4 - constexpr 和 const 的区别 二、decltype 关键字 2.1 - 推导规则 2.2 - 实际应用 一、constexpr 关键字 constexpr 是 C11 新引入的关键字不过在理解其具有用法和功能之前我们需要先理解 C 常量表达式。 所谓常量表达式指的是由多个 1常量组成的表达式换句话说如果表达式中的成员都是常量那么该表达式就是一个常量表达式这也意味着常量表达式一旦确定其值将无法修改。 实际开发中我们经常用到常量表达式以定义数组为例数组的长度就必须是一个常量表达式 int arr1[5] { 0, 1, 2, 3, 4 };  // ok int arr2[2 * 5] { 0 };  // ok // int len 10; // int arr3[len] { 0 }; // error 我们知道C 程序从编写完毕到执行分为四个阶段预处理、编译、汇编和链接得到可执行程序后就可以运行了。值得一提的是常量表达式和非常量表达式的计算时机不同非常量表达式只能在程序运行阶段计算出结果而常量表达式的计算往往发生在程序的编译阶段这可以大大地提高程序的执行效率 因为表达式只需要在编译阶段计算一次节省了每次程序运行时都要计算一次的时间。 对于用 C 编写的程序性能往往是永恒的追求那么在实际开发中如何才能判断一个表达式是否为常量表达式进而获得在编译阶段即可执行的 特权 呢除了人为判定外还有我们一开始所提到的 C11 新引入的 constexpr 关键字 。 constexpr 关键字的功能是使指定的常量表达式获得在程序编译阶段计算出结果的能力而不必等到程序运行阶段。在 C11 中constexpr 可用于修饰普通变量、函数包括普通函数、类的成员函数以及模板函数以及类的构造函数。 注意获得在程序编译阶段计算出结果的能力并不代表 constexpr 修饰的表达式一定会在程序编译阶段被执行具体的计算时机还是编译器说了算。 1.1 - constexpr 修饰普通变量 C11 中定义普通变量时可以用 constexpr 修饰从而使该变量获得在编译阶段即可计算出结果的能力。 注意使用 constexpr 修饰普通变量时变量必须经过初始化且初始值必须是一个常量表达式。 constexpr int len 10; int arr[len] { 0 };  // ok 在此示例中也可以将 constexpr 替换成 const即 const int len 10; int arr[len] { 0 };  // ok 注意const 和 constexpr 并不相同关于它们的区别 后面会进行详解。 1.2 - constexpr 修饰函数 constexpr 还可以用于修饰函数的返回值这样的函数又称为 常量表达式函数。 注意constexpr 并非可以修饰任意函数的返回值换句话说一个函数要想成为常量表达式必须满足如下三个条件 函数必须有返回值即函数的返回值类型不能是 void。 constexpr void func() { }  // 函数的返回值类型不能是 void 整个函数的函数体中除了可以包含 using 指令、typedef 语句以及 static_assert 断言以外只能包含一条 return 返回语句且 return 返回的表达式必须是常量表达式。 constexpr int func(int x) {constexpr int y 0;  // 函数体中只能包含一条 return 返回语句return 1 2 x y; } int y 0; constexpr int func(int x) {return 1 2 x y;  // return 返回的表达式必须是常量表达式 } #include iostream using namespace std; ​ constexpr int y 0; constexpr int func(int x) {return 1 2 x; } ​ int main() {int arr[func(3)] {  0 };cout sizeof(arr) endl;return 0; } 函数在使用之前必须有对应的定义语义。普通函数的调用只需要提前写好该函数的声明部分即可函数的定义部分可以放在调用位置之后甚至其他文件中但常量表达式函数在使用前必须要有该函数的定义。 #include iostream using namespace std; ​ constexpr int func(int x); ​ int main() {int arr[func(3)] {  0 };cout sizeof(arr) endl;return 0; } ​ constexpr int func(int x) {return 1 2 x; } 以上三个条件不仅对普通函数适用对类的成员函数和模板函数也适用。 但由于函数模板中的类型不确定因此实例化后的模板函数是否符合常量表达式函数的要求也是不确定的针对这种情况C11 规定如果 constexpr 修饰的实例化后的模板函数不满足常量表达式函数的要求则 constexpr 会被自动忽略即该函数就等同于一个普通函数。 1.3 - constexpr 修饰类的构造函数 如果想直接得到一个常量对象也可以使用 constexpr 修饰一个构造函数这样就可以得到一个常量构造函数。常量构造函数有一个要求构造函数的函数体必须为空且必须采用初始化列表的方式为各个成员赋值。 #include iostream using namespace std; ​ struct Person {const char* _name;int _age; ​constexpr Person(const char* name, int age): _name(name), _age(age){ } }; ​ int main() {constexpr Person p{ 张三, 18 };cout p._name : p._age endl;  // 张三:18return 0; } 1.4 - constexpr 和 const 的区别 在 C11 之前只有 const 关键字其在实际使用中经常会表现出两种不同的语义。 void func(const int num) {// int arr1[num] { 0 }; // errornum 是一个只读变量而不是常量const int count 5;int arr2[count] { 0 };  // okcount 是一个常量 } func 函数的参数 num 是一个只读变量其本质上仍然是变量而不是常量。 注意只读并不意味着不能被修改两者之间没有必然的联系例如 #include iostream using namespace std; ​ int main() {int a 520;const int ra a;a 1314;cout ra endl;  // 1314return 0; } 引用 ra 是只读的即无法通过自身去改变自己的值但并不意味着无法通过其他方式间接去改变通过改变 a 的值就可以改变 ra 的值。 func 函数体中的 count 则被看成是一个常量所以可以用来定义一个静态数组。 const int count 5; int* ptr (int*)count; *ptr 10; cout count endl; 为什么输出的 count 和 *ptr 不同呢 具体原因是 C 中的常量折叠或者常量替换将 const 常量放在符号表中给其分配内存但实际读取时类似于宏替换。 为了解决 const 关键字的双重语义问题C11 引入了新的关键字 constexpr建议凡是表达 只读 语义的场景都使用 const凡是表达 常量 语义的场景都使用 constexpr。 所以在上面的例子中在 func 函数体中使用 const int count 5; 是不规范的应使用 constexpr int count 5;。 二、decltype 关键字 decltype 是 C11 新增的一个关键字它和 auto 一样都用来在编译期间进行自动类型推导。 decltype 是 declare type 的缩写即 声明类型。 既然有了 auto为什么还需要 decltype 呢因为 auto 并不适用于所有的自动类型推导场景在某些特殊情况下auto 用起来非常不方便甚至压根无法使用所以 decltype 被引入到 C11 中。 auto 和 decltype 的语法格式 auto varname value;  // varname 表示变量名value 表示赋给变量的值 decltype(exp) varname[ value;]  // exp 表示一个表达式 auto 根据 右边的初始值 value 推导出变量的类型所以使用 auto 声明的变量必须初始化而 decltype 根据 exp 表达式推导出变量的类型跟 右边的初始值 value 没有关系所以不要求初始化。 示例 #include iostream using namespace std; ​ int main() {int x 0; ​decltype(x) y 1;decltype(x 3.14) z 5.5;decltype(x) ptr; ​cout typeid(y).name() endl;  // intcout typeid(z).name() endl;  // doublecout typeid(ptr).name() endl;  // int * ​// 注意// decltype 的推导是在编译期间完成的// 它只是用于表达式类型的推导并不会计算表达式的值decltype(x) i;cout x endl;  // 0return 0; } 2.1 - 推导规则 当程序员使用 decltype(exp) 获取类型时编译器将根据以下三条规则得出结果 如果表达式为普通变量、普通表达式或者类成员访问表达式那么 decltype(exp) 的类型就和表达式的类型一致。 #include iostream using namespace std; ​ class Test { public:string _str;static int _i; }; ​ int Test::_i 0; ​ int main() {int x 0;int r x;decltype(x) y x;  // y 被推导为 int 类型decltype(r) z x;  // z 被推导为 int 类型z;cout x r y z endl;  // 1 1 0 1 ​Test t;decltype(t._str) s hello world;  // s 被推导为 string 类型decltype(Test::_i) j 10;  // j 被推导为 int 类型return 0; } 如果表达式是函数调用那么 decltype(exp) 的类型和函数返回值一致。 #include iostream using namespace std; ​ // 函数声明 int func_int(); int func_int_r(); ​ const int func_c_int(); const int func_c_int_r(); ​ int main() {int x 0; ​decltype(func_int()) y x;  // y 被推导为 int 类型decltype(func_int_r()) z x;  // z 被推导为 int 类型z;cout x y z endl;  // 1 0 1 ​decltype(func_c_int()) m x;  // m 被推导为 int 类型m;cout x y z m  endl;  // 1 0 1 2 ​decltype(func_c_int_r()) n x;  // n 被推导为 const int 类型return 0; } 注意函数 func_c_int() 的返回值是一个纯右值即在表达式执行结束后不再存在的数据也就是临时性的数据对于纯右值而言只有类类型可以携带 const、volatile 限定符除此之外需要忽略这两个限定符因此 m 被推导为 int 类型而不是 const int 类型。 如果表达式是一个左值、或者被括号 () 包围那么 decltype(exp) 的类型就是表达式类型的引用即假设 exp 的类型为 T那么 decltype(exp) 的类型就是 T。 #include iostream using namespace std; ​ int main() {int x 0;decltype((x)) y x;  // y 被推导为 inty;cout x y endl;  // 1 1 ​decltype(x x 1) z x;  // z 被推导为 intz;cout x y z endl;  // 2 2 2return 0; } 2.2 - 实际应用 decltype 的应用多出现在泛型编程中。 #include vector using namespace std; ​ templateclass T class Test { public:void func(T container){_it container.begin();// do something ... ...} private:decltype(T().begin()) _it;// 当 T 是普通容器_it 为 T::iterator// 当 T 是 const 容器_it 为 T::const_iterator。 }; ​ int main() {vectorint v; Testvectorint t1;t1.func(v); ​const vectorint v2;Testconst vectorint t2;t2.func(v2);return 0; }
http://www.w-s-a.com/news/196275/

相关文章:

  • 河南建设工程协会网站网站收银系统建设
  • 网站制作 服务企业网站案例展示
  • 咸宁网站建设wordpress手动降级
  • 昆明做网站建设怎么样做网站赚钱全攻略
  • 企业网站建设实战教程微信如何注册小程序
  • 做一件代发网站百度seo服务
  • 小说网站开发 公司可以做行程的网站
  • 古交市网站建设公司apk连接wordpress
  • 网页 网 址网站区别wordpress菜单居右
  • 网站建设搭建运营一台云服务器做多个网站
  • 用php做网站用什么框架推广网站推荐
  • 如何用二级域名做网站多用户网上商城
  • 河南省建设科技网站浅谈电子商务网站建设与规划
  • 网站空间需要续费青海网站建设推广
  • 网站开发本地环境企业网站建设排名口碑
  • 做新闻的网站怎样赚钱个人网站课程设计报告
  • 网站设计样例那个网站做图片好看
  • 小型公司网站建设深圳网络营销策划有限公司
  • 国内优秀企业网站做视频网站用什么系统
  • 网站建设入门pdfwordpress网站标题
  • 专业网站的定义网站运营的概念
  • 外贸服装网站建设网页美工设计说明书
  • 郑州专业做网站公百度翻译api wordpress
  • 做网站哪里找大学的一级或二级域名
  • 没有静态ip可以做网站服务器上饶网站制作需要多少钱
  • 网站建设wangzhii做国外网站做什么内容
  • 网站建设 搞笑笑话经典 wordpress主题下载
  • 做网站要懂哪些wordpress 站点网络
  • 郑州外贸网站建设公司排名网站设计做啥好
  • 网站开发合同付款比例wordpress调用指定文章内容