Android C++系列:C++最佳实践6 constexpr与decltype

简介: 上一篇介绍了const关键字,主要修饰变量,起到不可改变的常量作用。有一种值不会改变并且在编译过程就能得到计算结果的表达式我们称为常量表达式。

image.png


1. 背景


上一篇介绍了const关键字,主要修饰变量,起到不可改变的常量作用。有一种值不会改变并且在编译过程就能得到计算结果的表达式我们称为常量表达式


字面值属于常量表达式,用常量表达式初始化的const对象也是常量表达式:


const int MAX = 100;//常量表达式
const int MAX_TIME = MAX * 60;//常量表达式
int size = 30;//不是常量表达式
const int size2 = getSize();//不是常量表达式


一个对象或者表达式是不是常量表达式由它的数据类型和初始值共同决定,但是在一些复杂的系统中,我们难以分辨一个初始值是不是常量表达式。如何让编译器帮助我们判断是否是常量表达式呢?


2. constexpr


C++11中,引入了关键字constexpr,允许将变量声明为constexpr类型以便由编译器来验证变量的值是否是常量表达式。

声明为constexpr的变量一定是一个常量,而且必须用常量表达式初始化:


constexpr int i = 200;
constexpr int j = i + 100;
constexpr int size = getSize();//getSize必须是constexpr函数


constexpr除了修饰变量还可以修饰函数,这种函数必须是编译时就可以计算到结果。


2.1 constexpr限制


常量表达式的值需要在编译时就得到计算,所以对声明constexpr时用到的类型必须有所限制。


把比较简单,值显而易见,容易计算的类型成为“字面值类型”。算术类型,引用类型和指针都属于字面值类型。


指针和引用都能定义成constexpr,但是它们的初始值必须是nullptr或者0,或者是存储于某个固定地址中的对象。


函数体内定义的变量一般不是存放在固定地址中,因此constexpr指针不能指向函数体内定义的指针。


constexpr声明中如果定义了指针,限定符constexpr仅对指针有效,与指针所指的对象无关。


3. decltype类型指示符


当我们希望从表达式的类型推断出要定义的变量的类型,但是不想用这个表达式的值初始化变量,这个时候就要用到了C++11引入的类型说明符decltype,它的作用是选择并返回操作数的数据类型:


decltype(fun()) i = x;//i的类型就是函数fun的返回类型


编译器分析fun表达式并得到它的类型,但是不进行实际调用。


3.1 引用在decltype的特殊之处


如果decltype使用的表达式不是一个变量,则decltype返回表达式结果对应的类型。有时有些表达式向decltype返回一个引用类型。这时意味着表达式的结果对象能作为一条赋值语句的左值。


如果表达式的内容是解引用操作,decltype将得到引用类型。


引用和指针本身是C++比Java多的引用和指针已经加大了编程语言的复杂度,现在为它们增加了新特性更是让人眼花缭乱,但是如果不弄明白一是遇到实际问题不知道用什么办法解决;二是看别人代码的时候容易一头雾水。


4. 类型别名


C/C++还有为类型定义别名的能力。比如我们用到的uint_8之类跨平台类型都是基于typedef方式命名的。


传统的别名定义是使用typedef:typedef char uint_8


C++11中引入了一种新的方法,使用using方式:using Str = std::string


使用typedef给复合类型起名容易踩坑,比如:


typedef char *str;
const str cstr = 0;//cstr是指向char的常量指针
const str *s;//s是一个指针,它的对象是指向char的常量指针


const是对给定类型的修饰,str是指向char的指针,因此const str就是指向char的常量指针,而不是指向常量字符的指针。

我们往往直接做替换:


const char *cstr = 0;


理解成指向常量字符的指针。


5. 总结


本文作为const内容的延续,介绍了constexpr和decltype两种修饰符,以及类型别名的两种方式,以及typedef别名使用容易遇到的问题。

目录
相关文章
|
存储 安全 算法
【C++智能指针 相关应用】深入探索C++智能指针:跨进程、动态库与最佳实践
【C++智能指针 相关应用】深入探索C++智能指针:跨进程、动态库与最佳实践
64 5
|
1月前
|
算法 编译器 数据库
【C++ 泛型编程 高级篇】使用SFINAE和if constexpr灵活处理类型进行条件编译
【C++ 泛型编程 高级篇】使用SFINAE和if constexpr灵活处理类型进行条件编译
246 0
|
4月前
|
C++
C++ 编程必备:对象生命周期管理的最佳实践
在C++中,对象的生命周期是指对象存在的时间段,从对象创建到对象销毁的整个过程。正确地管理对象的生命周期是编写高效、可靠C++代码的关键之一
65 1
|
4月前
|
存储 安全 编译器
【C++11特性篇】盘点C++11中三种简化声明的方式【auto】【decltype】【nullptr】(3)
【C++11特性篇】盘点C++11中三种简化声明的方式【auto】【decltype】【nullptr】(3)
|
1天前
|
安全 vr&ar C++
C++:编程语言的演变、应用与最佳实践
C++:编程语言的演变、应用与最佳实践
|
12天前
|
安全 Android开发 数据安全/隐私保护
Android中的动态权限请求与最佳实践
【4月更文挑战第14天】 在现代安卓应用开发中,用户隐私和安全被赋予了前所未有的重要性。随着Android 6.0(API级别23)引入的运行时权限模型,开发者必须更加细致地处理权限请求,以确保应用功能的完整性同时不侵犯用户的隐私。本文将深入探讨如何在Android应用中实现动态权限请求,分析常见问题,并提供一系列最佳实践,以帮助开发者优雅地处理这一挑战。
21 5
|
30天前
|
设计模式 安全 C++
【C++ const 函数 的使用】C++ 中 const 成员函数与线程安全性:原理、案例与最佳实践
【C++ const 函数 的使用】C++ 中 const 成员函数与线程安全性:原理、案例与最佳实践
71 2
|
1月前
|
存储 安全 编译器
【C++ 函数设计的艺术】深挖 C++ 函数参数的选择 智能指针与 std::optional:最佳实践与陷阱
【C++ 函数设计的艺术】深挖 C++ 函数参数的选择 智能指针与 std::optional:最佳实践与陷阱
110 0
|
1月前
|
算法 编译器 C++
【C++ 泛型编程 中级篇】C++ 编译时技术:探索 if constexpr 和 std::enable_if
【C++ 泛型编程 中级篇】C++ 编译时技术:探索 if constexpr 和 std::enable_if
40 0
|
1月前
|
安全 算法 程序员
【 C++14 新特性 加强版 constexpr】深入探索 C++14 中的 constexpr
【 C++14 新特性 加强版 constexpr】深入探索 C++14 中的 constexpr
48 0