[c++11]常量¶
参考:
Numeric, Boolean and Pointer Literals (C++)
String and character literals (C++)
常量(literal
)指的是直接表示值的程序元素,常用于初始化命名变量和将参数传递给函数。按类型可分为以下几种:
- 整数常量(
integer literal
) - 浮点数常量(
floating-point literal
) - 布尔常量(
boolean literal
) - 指针常量(
pointer literal
) - 字符常量(
character literal
) - 字符串常量(
string literal
) - 自定义常量(
user-defined literal
)
如果要指定特定的常量类型,可以为其添加前缀(prefix
)和后缀(suffix
)。比如16
进制值0x35
,长整型数123L
整数常量¶
- 整型常量以数字开头,没有小数或指数部分
- 可以指定十进制(
Decimal
)、八进制(Octal
)或十六进制(Hexadecimal
)形式的整型常量 - 可以指定有符号(
unsigned
)或无符号(unsigned
)类型以及长(long
)或短(short
)类型
默认整数常量的类型是int
(32
位),如果常量超出32
位,则给定类型为long long
(64
位)
八/十/十六进制¶
八进制整数常量以0
开头,十六进制整数常量以0x
开头,十进制整数常量没有前缀
int a = 32;
int b = 040;
int c = 0x20;
// 以十进制输出
cout << a << endl;
cout << b << endl;
cout << c << endl;
// 以各自进制输出
cout << std::dec << a << endl;
cout << std::oct << b << endl;
cout << std::hex << c << endl;
整数常量类型¶
- 指定无符号整数类型,加上前缀
u
或U
- 指定长整数类型,加上后缀
l
或L
。比如指定64位整数类型,加上ll
或LL
后缀
数字分隔符¶
为便于阅读,可以使用单引号字符(single-quote
)为较大的数字分隔位置。分隔符对编译没有影响
int i = 123'456'789;
long j = 0x123'456'789;
cout << i << endl;
cout << std::hex << j << endl;
浮点数常量¶
浮点数常量必须包含小数部分,必须包含小数点(.
)并且可以包含指数
- 使用尾数指定常量的小数部分
- 使用指数(
exponent
)指定常量的量级(magnitude
):将数字大小指定为10
的幂
指数¶
使用e
或E
指定,后跟可选符号(+
或-
)以及一串数字。如果指数存在可以不包含小数点
// a = 1220
double a = 1.22e3;
cout << a << endl;
// b = 0.00122
double b = 1.22e-3;
cout << b << endl;
浮点数常量类型¶
默认浮点数常量为double
类型(64
位),可以使用后缀名f
或者l
(也可以使用大写形式)分别指定为float
(32
位)或long double
(64
位)
虽然long double
和double
具有相同的表示形式,但它们不是相同的类型
float a = 1.22e3f;
long double b = 1.22e-3l;
布尔常量¶
布尔常量是true
和false
bool a = true;
bool b = false;
// 整数 1
cout << a << endl;
// 整数 0
cout << b << endl;
指针常量¶
c++11
开始新增了一个指针常量 - nullptr
字符常量¶
字符常量由常量字符组成,它由单引号包围的字符表示。有五种类型的字符常量:
- 普通的
char
类型的字符常量,比如'a'
utf-8
格式的char
类型字符常量,比如u8'a'
(c++20
开始)wchar_t
类型的宽字符常量,比如L'a'utf-16
格式的char16_t
类型字符常量,比如u'a'
utf-32
格式的char32_t
类型字符常量,比如U'a'
用于字符常量的字符可以是任何字符,除了保留字符反斜杠/
、单引号'
或换行符\n
,不过可以使用转义序列指定保留字符;也可以使用通用字符名指定字符,只要类型足够大以容纳字符
转义序列¶
常用的转义序列包括
- 换行(
newline
)-\n
- 反斜杠(
backslash
)-\\
- 水平制表符(
horizontal tab
)-\t
- 垂直制表符(
vertical tab
)-\v
- 单引号(
single quote
)-\'
- 双引号(
double quote
)-\"
- 空字符(
the null character
)-\0
- 空格(
backspace
)-\b
- 问号(
question mark
)-?
或\?
char newline = '\n';
char tab = '\t';
char backspace = '\b';
char backslash = '\\';
char nullChar = '\0';
cout << "Newline character: " << newline << "ending" << endl; // Newline character:
// ending
cout << "Tab character: " << tab << "ending" << endl; // Tab character : ending
cout << "Backspace character: " << backspace << "ending" << endl; // Backspace character : ending
cout << "Backslash character: " << backslash << "ending" << endl; // Backslash character : \ending
cout << "Null character: " << (void *) nullChar << "ending" << endl; //Null character: ending
字符串常量¶
字符串常量表示以空字符结尾的字符序列,且字符必须用双引号括起来
// 赋值字符数组
char a[3] = "12";
// 赋值字符指针
const char *b = "12";
// 可以添加后缀s表示转换成std::string
std::string ss = "12"s;
自定义常量¶
有5
种主要类别的常量:整数、浮点数、字符、字符串和布尔常量。从c++11
开始,可以利用这些常量进行自定义,为常见习惯用法(common idioms
)提供语法快捷方式并提高类型安全性
用户定义的常量没有性能优势或劣势;它们主要是为了方便或编译时的类型推导。标准库提供了自定义常量类型std::string、std::complex
用户定义的常量运算符签名¶
在命名空间范围内使用以下形式操作operator""
,可以实现用户自定义常量:
ReturnType operator "" _a(unsigned long long int); // Literal operator for user-defined INTEGRAL literal
ReturnType operator "" _b(long double); // Literal operator for user-defined FLOATING literal
ReturnType operator "" _c(char); // Literal operator for user-defined CHARACTER literal
ReturnType operator "" _d(wchar_t); // Literal operator for user-defined CHARACTER literal
ReturnType operator "" _e(char16_t); // Literal operator for user-defined CHARACTER literal
ReturnType operator "" _f(char32_t); // Literal operator for user-defined CHARACTER literal
ReturnType operator "" _g(const char*, size_t); // Literal operator for user-defined STRING literal
ReturnType operator "" _h(const wchar_t*, size_t); // Literal operator for user-defined STRING literal
ReturnType operator "" _i(const char16_t*, size_t); // Literal operator for user-defined STRING literal
ReturnType operator "" _g(const char32_t*, size_t); // Literal operator for user-defined STRING literal
ReturnType operator "" _r(const char*); // Raw literal operator
template<char...> ReturnType operator "" _t(); // Literal operator template
- 运算符名称
a/b/c/...
是占位符 - 下划线(
the leading underscore
)是必须的(只有标准库中的自定义常量可以不用下划线) - 返回值根据需要进行指定
- 自定义常量也可被定义为
constexpr
定义结构体Distance
,自定义常量_km
和_m
用于转换千米和米,
struct Distance {
public:
long double get_meters() { return meters; }
Distance operator+(Distance &other) {
return Distance(get_meters() + other.get_meters());
}
private:
friend Distance operator "" _km(long double val);
friend Distance operator "" _m(long double val);
explicit Distance(long double val) : meters(val) {}
// 定义私有成员,保存米数
long double meters{0};
};
Distance operator "" _km(long double val) {
return Distance(val * 1000);
}
Distance operator "" _m(long double val) {
return Distance(val);
}
int main() {
// Must have a decimal point to bind to the operator we defined!
Distance d{402.0_m}; // construct using kilometers
cout << "meters in d: " << d.get_meters() << endl; // 402
Distance d2{4.02_m}; // construct using miles
cout << "meters in d2: " << d2.get_meters() << endl; // 4020
Distance d3 = 4.2_km;
Distance d4 = 36.0_m;
// add distances constructed with different units
Distance d5 = d3 + d4;
cout << "d5 value = " << d5.get_meters() << endl; // 99.6
// 不能调用私有构造函数
// Distance d6(90.0); // error constructor not accessible
string s;
getline(std::cin, s);
return 0;
}
常量使用规范¶
不推荐直接在表达式或语句中使用常量,这通常被称为魔法常量(magic constants
),更好的方式是使用具有明确含义的命名常量,这有助于上下文理解