这一章是C++的基石,虽然内容比较基础,但极其重要,很多概念会贯穿整个C++学习过程。
2.1 基本内置类型
C++定义了一组基本算术类型:
整数类型
#include <iostream>
int main()
{
bool flag = true; // 布尔类型:true 或 false,1字节
char ch = 'A'; // 字符类型,1字节
wchar_t wch = L'中'; // 宽字符,用于扩展字符集
short s = 100; // 短整型,通常2字节
int i = 1000; // 整型,通常4字节
long l = 100000L; // 长整型,通常4或8字节
long long ll = 1000000LL;// 长长长整型,通常8字节
std::cout << "bool: " << flag << std::endl;
std::cout << "char: " << ch << std::endl;
std::cout << "int: " << i << std::endl;
return 0;
}
浮点类型
#include <iostream>
int main()
{
float f = 3.14f; // 单精度浮点数,通常4字节
double d = 3.1415926; // 双精度浮点数,通常8字节
long double ld = 3.141592653589793238L; // 扩展精度浮点数
std::cout << "float: " << f << std::endl;
std::cout << "double: " << d << std::endl;
std::cout << "long double: " << ld << std::endl;
return 0;
}
2.2 类型转换
隐式类型转换
#include <iostream>
int main()
{
// 布尔转换:非零为true,零为false
bool b = 3; // b = true
bool b2 = 0; // b2 = false
// 浮点转整数:截断小数部分
int i = 3.14; // i = 3
// 整数转浮点:添加小数部分
double d = 3; // d = 3.0
// 无符号整数溢出:取模
unsigned char c = -1; // c = 255 (因为-1 mod 256 = 255)
std::cout << "bool b: " << b << std::endl;
std::cout << "int i from 3.14: " << i << std::endl;
std::cout << "unsigned char c from -1: " << (int)c << std::endl;
return 0;
}
显式类型转换
#include <iostream>
int main()
{
int i = 10;
double d = 3.14;
// C风格强制转换
int truncated = (int)d; // truncated = 3
// 函数风格强制转换
int truncated2 = int(d); // truncated2 = 3
// static_cast(C++推荐方式)
double result = static_cast<double>(i) / 4; // result = 2.5
std::cout << "truncated: " << truncated << std::endl;
std::cout << "result: " << result << std::endl;
return 0;
}
2.3 变量声明和定义
#include <iostream>
// 声明(在头文件中常见)
extern int global_var; // 声明global_var,定义在其他文件
// 定义(分配存储空间)
int global_var = 100; // 定义global_var
int main()
{
// 定义并初始化变量
int units_sold = 0;
int units_sold2 = {0}; // 列表初始化(C++11)
int units_sold3{0}; // 列表初始化(C++11)
int units_sold4(0); // 直接初始化
// 默认初始化
std::string empty_str; // 空字符串
int local_var; // 未初始化!值不确定
std::cout << "global_var: " << global_var << std::endl;
std::cout << "empty_str: '" << empty_str << "'" << std::endl;
// 注意:局部内置类型变量不会自动初始化!
// std::cout << local_var << std::endl; // 危险!值不确定
return 0;
}
2.4 复合类型
引用(Reference)
#include <iostream>
int main()
{
int value = 42;
int &ref = value; // ref是value的引用(别名)
std::cout << "value: " << value << std::endl; // 42
std::cout << "ref: " << ref << std::endl; // 42
ref = 100; // 通过引用修改原变量
std::cout << "value after change: " << value << std::endl; // 100
// 引用必须在定义时初始化
// int &ref2; // 错误!引用必须初始化
// 引用一旦绑定就不能重新绑定到其他对象
int another = 200;
// &ref = another; // 错误!不能重新绑定
return 0;
}
指针(Pointer)
#include <iostream>
int main()
{
int value = 42;
int *ptr = &value; // ptr指向value(存储value的地址)
std::cout << "value: " << value << std::endl; // 42
std::cout << "ptr: " << ptr << std::endl; // 地址值
std::cout << "*ptr: " << *ptr << std::endl; // 42(解引用)
*ptr = 100; // 通过指针修改原变量
std::cout << "value after change: " << value << std::endl; // 100
// 指针可以重新指向其他对象
int another = 200;
ptr = &another; // ptr现在指向another
std::cout << "*ptr after reassign: " << *ptr << std::endl; // 200
// 空指针的几种表示方法
int *p1 = nullptr; // C++11推荐(最安全)
int *p2 = 0; // 传统方式
int *p3 = NULL; // C传统方式(在cstdlib中定义)
return 0;
}
2.5 const限定符
基本const用法
#include <iostream>
int main()
{
const int bufSize = 512; // 定义常量
// bufSize = 1024; // 错误!不能修改const变量
const int i = get_size(); // 运行时初始化
const int j = 42; // 编译时初始化
const int k; // 错误!const变量必须初始化
// const对象默认只在文件内有效
// 如果想在多个文件间共享const对象,需要在定义和声明前都加extern
return 0;
}
const与引用(常量引用)
#include <iostream>
int main()
{
int i = 42;
const int &r1 = i; // 正确:允许将const int&绑定到普通int上
const int &r2 = 42; // 正确:常量引用可以绑定到字面值
const int &r3 = r1 * 2; // 正确:常量引用可以绑定到表达式结果
// int &r4 = 42; // 错误:普通引用不能绑定到字面值
std::cout << "r1: " << r1 << std::endl;
std::cout << "r2: " << r2 << std::endl;
std::cout << "r3: " << r3 << std::endl;
return 0;
}
const与指针
#include <iostream>
int main()
{
int value = 42;
int another = 100;
// 指向常量的指针(pointer to const)
const int *ptr1 = &value; // ptr1指向一个常量
// *ptr1 = 50; // 错误!不能通过ptr1修改value
ptr1 = &another; // 正确!ptr1可以指向其他对象
// 常量指针(const pointer)
int *const ptr2 = &value; // ptr2本身是常量
*ptr2 = 50; // 正确!可以通过ptr2修改value
// ptr2 = &another; // 错误!ptr2不能指向其他对象
// 指向常量的常量指针
const int *const ptr3 = &value; // ptr3本身是常量,指向的对象也是常量
// *ptr3 = 50; // 错误!
// ptr3 = &another; // 错误!
std::cout << "value: " << value << std::endl; // 50
return 0;
}
2.6 类型别名与auto
类型别名
#include <iostream>
// 使用typedef创建类型别名
typedef double wages; // wages是double的别名
typedef wages base, *p; // base是double的别名,p是double*的别名
// 使用using创建类型别名(C++11)
using salary = double; // salary是double的别名
int main()
{
wages hourly = 25.5; // 相当于 double hourly = 25.5;
salary monthly = 5000.0; // 相当于 double monthly = 5000.0;
std::cout << "时薪: " << hourly << std::endl;
std::cout << "月薪: " << monthly << std::endl;
return 0;
}
auto类型说明符(C++11)
#include <iostream>
#include <typeinfo>
int main()
{
int i = 42;
const int ci = i;
// auto让编译器自动推断类型
auto a = i; // a是int
auto b = ci; // b是int(顶层const被忽略)
auto c = &i; // c是int*
auto d = &ci; // d是const int*(底层const保留)
// 引用和auto
auto &e = ci; // e是const int&
// auto &f = 42; // 错误!不能为非常量引用绑定字面值
const auto &g = 42; // 正确!可以为常量引用绑定字面值
std::cout << "type of a: " << typeid(a).name() << std::endl;
std::cout << "type of d: " << typeid(d).name() << std::endl;
return 0;
}
📝 第二章关键要点总结
-
内置类型选择:
- 算术运算:用
int或double - 明确知道不可能为负:用
unsigned - 字符:用
char - 布尔:用
bool
- 算术运算:用
-
引用vs指针:
- 引用:别名,必须初始化,不能重新绑定
- 指针:存储地址,可以重新指向,可以为空
-
const用法:
const int*:指向常量的指针(底层const)int* const:常量指针(顶层const)const int&:常量引用
-
初始化:
- 局部内置类型变量不会自动初始化
- 类类型变量有默认初始化
- 推荐使用列表初始化
{}
这一章的概念非常重要,特别是指针、引用和const,它们会在整个C++学习中反复出现。如果有任何不清楚的地方,建议多写代码实验!

2123

被折叠的 条评论
为什么被折叠?



