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 单冒号:(多重语义,极易混淆)

:不属于运算符,属于语法分隔标记,在四种场景拥有完全不同含义:

  1. 类继承定义
  2. 构造函数初始化列表
  3. 三目运算符?:
  4. 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; }

常见错误:对象使用->、指针使用.,编译直接报错。

三、星号*多重语义

*根据上下文拥有四种核心含义:乘法运算符、指针声明、解引用、函数指针。

  1. 算术乘法:a * b
  2. 指针类型标记:int* p
  3. 解引用运算符:*p,取出指针指向内存的值
#include <iostream> using namespace std; int main() { // 1.乘法运算 int a = 3 * 5; cout << a << endl; int num = 100; // 2.指针声明 int* p = &num; // 3.解引用 cout << *p << endl; *p = 200; cout << num << endl; return 0; }

四、& 符号多重语义

&三种用途:按位与运算符、取地址运算符、引用声明(C++ 独有)

  1. a & b:按位与运算
  2. &val:取变量内存地址
  3. int& ref:左值引用声明
#include <iostream> using namespace std; int main() { // 按位与 int x = 6 & 3; cout << "6 & 3 = " << x << endl; int num = 10; // 取地址 int* p = &num; cout << "num地址:" << p << endl; // 左值引用 int& ref = num; ref = 999; cout << num << endl; return 0; }

拓展:&&双重与,两种语义

  1. a && b逻辑与运算符(短路运算)
  2. 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>>

六、移位运算符 <<>>

两种语义:

  1. 位运算:左移<<、右移>>
  2. 流运算符(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 圆括号()

  1. 函数调用、函数声明func()
  2. 表达式优先级调整(a+b)*c
  3. 强制类型转换(int)val
  4. 值初始化int num(10)

7.2 方括号[]

  1. 数组下标访问arr[0]
  2. operator [] 重载
  3. 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 注释符号

//单行注释;/* */块注释

十四、极易混淆符号对照表总结

  1. ::作用域解析 |.对象成员访问 |->指针成员访问
  2. &:引用 / 取地址 / 按位与 |&&:逻辑与 / 右值引用
  3. *:乘法 / 指针 / 解引用
  4. =赋值 |==判断相等
  5. <比较小于 |<>模板参数包裹
  6. <<左移运算 /cout 输出
  7. :多种语法标记 |?:三目运算符

十五、综合易错知识点总结

  1. 符号语义依赖上下文,不存在绝对固定含义,不能死记单一功能;
  2. 区分运算符优先级:()>++/*/&> 算术运算 > 比较运算 > 逻辑运算 >=赋值;复杂表达式尽量加括号消除歧义;
  3. 不要混淆对象.与指针->,是新手最高频编译错误;
  4. &*在声明和表达式中含义完全不同;
  5. &&兼具逻辑运算与右值引用两种无关语义,不要互相混淆;
  6. 模板<>和比较运算符<仅仅外观一致,语法层级完全无关;
  7. 逗号运算符极易被忽视,在循环、赋值语句容易产生预期之外结果;
  8. 区分初始化列表{}、函数调用()、数组[]三类括号使用场景。