C++ 各类特殊符号、运算符
前言
在 C++ 语法体系中,存在大量形态简短、多重语义的符号。很多符号外观相同,但是处在不同上下文时代表完全不同的功能,例如::、:、.、->、*、&、<>等,是 C++ 入门阶段最容易混淆,同时也是笔试、面试高频考察内容。C 语言基础只覆盖基础算术、位运算,而 C++ 扩展出作用域符号、成员访问、模板标记、lambda 捕获、初始化列表、三元运算符、右值引用、范围 for 冒号等全新语法符号。
不少开发者长期只凭经验使用各类符号,分不清运算符优先级、不同场景下符号语义差异,极易产生隐蔽 BUG:比如混淆.和->、区分不开取地址&与引用&、误把==写成=、看不懂模板<>、无法分辨左值引用与右值引用&&。
本文将按照功能对 C++ 所有常用符号、运算符进行系统性归类讲解,区分语法标记符与运算符,每个知识点配备可直接编译运行的代码示例,辨析易错场景、相似符号对比
一、作用域与归属标记符号
1.1 作用域解析运算符::
::是 C++ 独有的运算符,名称:作用域解析运算符。核心功能:明确指定标识符所属作用域,打破局部名字遮蔽,区分全局、命名空间、类作用域。 适用场景:访问全局变量、命名空间成员、类静态成员、定义类外成员函数。
示例 1:区分局部变量与全局变量
#include <iostream> using namespace std; int data = 100; // 全局变量 int main() { int data = 10; // 局部变量遮蔽全局变量 cout << "局部data = " << data << endl; cout << "全局data = " << ::data << endl; // ::直接访问全局作用域 return 0; }示例 2:命名空间访问
#include <iostream> namespace CustomNs { void func() { std::cout << "自定义命名空间函数执行" << std::endl; } int val = 888; } int main() { CustomNs::func(); std::cout << CustomNs::val << std::endl; return 0; }示例 3:类外部定义成员函数、访问静态成员
#include <iostream> using namespace std; class Demo { public: static int num; void show(); }; // 类外定义成员函数:类名::函数名 void Demo::show() { cout << "类外部实现的成员函数" << endl; } // 静态成员初始化 int Demo::num = 66; int main() { Demo d; d.show(); cout << Demo::num << endl; return 0; }1.2 单冒号:(多重语义,极易混淆)
:不属于运算符,属于语法分隔标记,在四种场景拥有完全不同含义:
- 类继承定义
- 构造函数初始化列表
- 三目运算符
?: - C++11 范围 for 循环
示例 1:继承语法
#include <iostream> using namespace std; class Base{}; // : 表示继承关系,public为继承方式 class Son : public Base { }; int main() { Son s; return 0; }示例 2:构造函数初始化列表
#include <iostream> #include <string> using namespace std; class Person { private: int age; string name; public: // : 后跟随初始化列表,优先于构造函数体执行 Person(int a, string n): age(a), name(n) { cout << name << "," << age << endl; } }; int main() { Person p(20, "小明"); return 0; }示例 3:范围 for 循环 C++11
#include <iostream> #include <vector> using namespace std; int main() { vector<int> vec{1,2,3,4,5}; // : 分隔变量与容器 for(auto v : vec) { cout << v << " "; } return 0; }示例 4:三元运算符条件 ? 表达式1 : 表达式2
#include <iostream> using namespace std; int main() { int a = 10, b = 20; int maxVal = a > b ? a : b; cout << maxVal << endl; return 0; }二、成员访问符号.与->
二者功能都是访问类 / 结构体成员,使用场景严格区分:
.:对象实例(栈对象、引用)访问成员->:指针访问对象成员;ptr->member等价于(*ptr).member
示例对比:
#include <iostream> using namespace std; struct Student { int id; void print() { cout << "学号:" << id << endl; } }; int main() { Student s; s.id = 1001; s.print(); // 对象 . 成员 Student* p = &s; p->id = 1002; p->print(); // 指针 -> 成员 (*p).id = 1003; (*p).print(); Student& ref = s; ref.id = 1004; ref.print(); // 引用使用 . return 0; }常见错误:对象使用
->、指针使用.,编译直接报错。
三、星号*多重语义
*根据上下文拥有四种核心含义:乘法运算符、指针声明、解引用、函数指针。
- 算术乘法:
a * b - 指针类型标记:
int* p - 解引用运算符:
*p,取出指针指向内存的值
#include <iostream> using namespace std; int main() { // 1.乘法运算 int a = 3 * 5; cout << a << endl; int num = 100; // 2.指针声明 int* p = # // 3.解引用 cout << *p << endl; *p = 200; cout << num << endl; return 0; }四、& 符号多重语义
&三种用途:按位与运算符、取地址运算符、引用声明(C++ 独有)
a & b:按位与运算&val:取变量内存地址int& ref:左值引用声明
#include <iostream> using namespace std; int main() { // 按位与 int x = 6 & 3; cout << "6 & 3 = " << x << endl; int num = 10; // 取地址 int* p = # cout << "num地址:" << p << endl; // 左值引用 int& ref = num; ref = 999; cout << num << endl; return 0; }拓展:&&双重与,两种语义
a && b逻辑与运算符(短路运算)int&& rref右值引用(C++11)
#include <iostream> using namespace std; void func(int&& r) { cout << "右值引用接收:" << r << endl; } int main() { // 逻辑与 bool res = (10 > 5) && (3 > 1); cout << res << endl; func(500); // 传入临时右值 return 0; }五、模板尖括号<>
<>是模板语法标记,不属于比较运算符。用于类模板、函数模板声明与实例化。 区分:a < b是小于运算符;Template<Type>是模板参数列表。
#include <iostream> #include <vector> using namespace std; // 函数模板 template<typename T> T maxNum(T a, T b) { return a > b ? a : b; } int main() { cout << maxNum<int>(11,22) << endl; vector<int> vec; // vector<int> <>包裹模板参数 return 0; }C++11 语法坑:
>>在模板末尾,旧标准必须空格vector<vector<int> >;C++11 开始支持vector<vector<int>>。
六、移位运算符 <<>>
两种语义:
- 位运算:左移
<<、右移>> - 流运算符(C++ 重载):
cout <<、cin >>
#include <iostream> using namespace std; int main() { // 位运算左移 int a = 1 << 3; cout << "1 << 3 = " << a << endl; // 流输出运算符 cout << "测试输出" << endl; int input; cin >> input; return 0; }七、括号系列符号()[]{}
7.1 圆括号()
- 函数调用、函数声明
func() - 表达式优先级调整
(a+b)*c - 强制类型转换
(int)val - 值初始化
int num(10)
7.2 方括号[]
- 数组下标访问
arr[0] - operator [] 重载
- lambda 捕获:
[=][&]
7.3 大括号{}C++11 统一初始化列表
#include <iostream> #include <vector> using namespace std; int main() { // 统一列表初始化 int a{100}; int arr[]{1,2,3}; vector<int> v{5,6,7}; // lambda表达式 []捕获 ()参数 {}函数体 auto lambda = [](int x){ cout << x << endl; }; lambda(99); return 0; }八、关系、逻辑运算符
==等于 ;!=不等于;><>=<=逻辑:&&逻辑与,||逻辑或,!逻辑非 重点区分:=赋值运算符,==比较相等,新手高频错误。
#include <iostream> using namespace std; int main() { int a = 10; if (a == 10) // 判断相等 { cout << "相等" << endl; } // if(a=20) 是赋值,永远成立,隐蔽BUG return 0; }九、位运算符汇总
~按位取反、&按位与、|按位或、^按位异或、<<左移、>>右移
#include <iostream> using namespace std; int main() { int x = 5; // 0101 int y = 3; // 0011 cout << (x & y) << endl; cout << (x | y) << endl; cout << (x ^ y) << endl; return 0; }十、赋值复合运算符
=、+=、-=、*=、/=、%=、&=、|=、^=、<<=、>>=
#include <iostream> using namespace std; int main() { int num = 10; num += 5; num *= 2; cout << num << endl; return 0; }十一、自增自减运算符 ++ --
前置++a、后置a++;-- 同理。 前置:先自增,返回自增后值(左值) 后置:先返回原值,再自增(右值)
#include <iostream> using namespace std; int main() { int a = 10; cout << a++ << endl; //输出10 cout << ++a << endl; //输出12 return 0; }十二、Lambda 表达式专用符号
[]捕获列表、()参数、mutable、->尾随返回类型 语法格式:[捕获](参数) -> 返回类型 {函数体}
#include <iostream> using namespace std; int main() { int num = 100; // -> 指定lambda返回值类型 auto func = [num](int x) -> int{ return num + x; }; cout << func(20) << endl; return 0; }十三、其它特殊符号
13.1.点号与.*、->*
成员指针运算符,日常使用较少,用于类成员指针访问:
#include <iostream> using namespace std; class Test { public: int val = 666; }; int main() { Test t; int Test::*p = &Test::val; cout << t.*p << endl; Test* pt = &t; cout << pt->*p << endl; return 0; }13.2 逗号运算符,
逗号表达式,从左向右执行,返回最右侧结果
#include <iostream> using namespace std; int main() { int a = (1+2, 3+4, 10); cout << a << endl; //输出10 return 0; }13.3 单引号 ' ' 字符常量;双引号 " " 字符串字面量
char ch = 'A'; const char* str = "hello";13.4 注释符号
//单行注释;/* */块注释
十四、极易混淆符号对照表总结
::作用域解析 |.对象成员访问 |->指针成员访问&:引用 / 取地址 / 按位与 |&&:逻辑与 / 右值引用*:乘法 / 指针 / 解引用=赋值 |==判断相等<比较小于 |<>模板参数包裹<<左移运算 /cout 输出:多种语法标记 |?:三目运算符
十五、综合易错知识点总结
- 符号语义依赖上下文,不存在绝对固定含义,不能死记单一功能;
- 区分运算符优先级:
()>++/*/&> 算术运算 > 比较运算 > 逻辑运算 >=赋值;复杂表达式尽量加括号消除歧义; - 不要混淆对象
.与指针->,是新手最高频编译错误; &与*在声明和表达式中含义完全不同;&&兼具逻辑运算与右值引用两种无关语义,不要互相混淆;- 模板
<>和比较运算符<仅仅外观一致,语法层级完全无关; - 逗号运算符极易被忽视,在循环、赋值语句容易产生预期之外结果;
- 区分初始化列表
{}、函数调用()、数组[]三类括号使用场景。
