大家好,我是你的C++学习伙伴。今天我们来聊聊C++中两个最容易让人困惑的符号:*
和 &
。作为C++小白,你可能在代码中看到它们就头大,因为它们不是单一含义的符号,而是根据上下文有不同的用法。如果不搞清楚,很容易写出bug,或者读不懂别人的代码。
这篇文章会从零基础出发,一步步拆解*
和&
的各种用法,提供简单易懂的例子。读完后,你会彻底搞懂它们!我们假设你已经了解了C++的基本语法(如变量、函数),如果没有,先去补补基础哦。
为什么*和&这么“多面”?
在C++中,*
和 &
是操作符重载的典型例子。它们根据位置和上下文,有不同的含义。这是因为C++继承了C语言的指针和引用机制,同时还保留了数学运算符。别担心,我们一个个来拆解。
先从 &
开始,因为它相对简单一些。
& 的三种主要用法
&
在C++中有三种常见用法:取地址、引用声明、按位与运算。记住,上下文决定一切!
1. 取地址运算符(Address-of Operator)
- 作用:获取一个变量的内存地址。
- 用法:放在变量名前,如
&var
。 - 什么时候用:当你需要指针指向某个变量时。
简单解释:想象变量是房子,&
就是取房子的门牌号(地址)。
代码例子:
#include <iostream>
int main() {
int num = 10; // 一个普通变量
int* ptr = # // &num 获取num的地址,赋给指针ptr
std::cout << "num的值: " << num << std::endl; // 输出: 10
std::cout << "num的地址: " << &num << std::endl; // 输出: 某个内存地址,如0x7ffeefbff5a8
std::cout << "ptr指向的值: " << *ptr << std::endl; // 输出: 10(稍后解释*)
return 0;
}
- 这里,
&num
不是运算,而是直接给出num
在内存中的位置。指针ptr
存的就是这个地址。
小白注意:地址通常是十六进制数,别试图直接操作它,除非你懂指针。
2. 引用声明(Reference Declarator)
- 作用:创建一个变量的“别名”,修改引用就等于修改原变量。
- 用法:在声明变量时用,如
int& ref = var;
。 - 什么时候用:函数参数传递时,避免拷贝大对象;或简化代码。
简单解释:引用就像变量的“影子”,动影子就动本体。没有额外的内存开销。
代码例子:
#include <iostream>
int main() {
int num = 10;
int& ref = num; // ref是num的引用(别名)
ref = 20; // 修改ref,num也会变
std::cout << "num的值: " << num << std::endl; // 输出: 20
std::cout << "ref的值: " << ref << std::endl; // 输出: 20
return 0;
}
- 注意:引用必须初始化(绑定到一个变量),一旦绑定就不能改绑其他变量。引用不是指针,但很像“安全的指针”。
函数中的应用(小白进阶):
void swap(int& a, int& b) { // 按引用传递,避免拷贝
int temp = a;
a = b;
b = temp;
}
int main() {
int x = 1, y = 2;
swap(x, y); // x和y的值互换
// ...
}
3. 按位与运算符(Bitwise AND)
- 作用:对两个整数的二进制位进行“与”运算(都为1才为1)。
- 用法:在表达式中,如
a & b
。 - 什么时候用:位操作,比如掩码、权限检查。
简单解释:忽略高深的东西,就当是数学运算,但针对二进制。
代码例子:
#include <iostream>
int main() {
int a = 5; // 二进制: 101
int b = 3; // 二进制: 011
int result = a & b; // 结果: 001 (十进制1)
std::cout << "a & b = " << result << std::endl; // 输出: 1
return 0;
}
- 这和取地址/引用的
&
完全不同,因为这里是两个操作数之间的运算。
小白提示:如果代码报错“expected unqualified-id”,可能是把 &
当成取地址用了,但上下文不对。
* 的三种主要用法
*
比 &
更常见,也更易混淆。它有乘法、指针声明、解引用三种用法。
1. 乘法运算符(Multiplication Operator)
- 作用:两个数的乘积。
- 用法:在表达式中,如
a * b
。 - 什么时候用:数学计算。
简单解释:就是小学数学的乘法,没啥特别。
代码例子:
#include <iostream>
int main() {
int a = 5;
int b = 3;
int result = a * b; // 15
std::cout << "a * b = " << result << std::endl; // 输出: 15
return 0;
}
- 这最简单,不会和指针混淆,因为上下文是数值运算。
2. 指针声明(Pointer Declarator)
- 作用:声明一个指针变量。
- 用法:在类型后,如
int* ptr;
(ptr是一个指向int的指针)。 - 什么时候用:需要操作内存地址时。
简单解释:指针是“箭头”,指向变量的地址。*
在这里表示“指向”。
代码例子:
#include <iostream>
int main() {
int num = 10;
int* ptr; // 声明指针
ptr = # // 赋值地址
std::cout << "ptr的值(地址): " << ptr << std::endl;
return 0;
}
- 注意:
*
紧挨类型,声明时不带空格(如int *ptr;
也行,但风格因人而异)。多个指针声明时,要小心:int* p1, p2;
中 p2 不是指针!
3. 解引用运算符(Dereference Operator)
- 作用:通过指针访问它指向的变量值。
- 用法:放在指针变量前,如
*ptr
。 - 什么时候用:读/写指针指向的内容。
简单解释:*ptr
就是“取出箭头指向的东西”。
代码例子(结合取地址):
#include <iostream>
int main() {
int num = 10;
int* ptr = #
*ptr = 20; // 通过解引用修改num的值
std::cout << "num的值: " << num << std::endl; // 输出: 20
std::cout << "*ptr的值: " << *ptr << std::endl; // 输出: 20
return 0;
}
- 如果指针没初始化就解引用,会崩溃(空指针异常)!小白常见错误。
小白进阶:指针和数组的关系。数组名就是指针:
int arr[3] = {1, 2, 3};
int* p = arr; // p指向arr[0]
std::cout << *p << std::endl; // 1
常见混淆和注意事项
- & 和 * 的搭配:指针和引用常一起用。引用可以看作“自动解引用的指针”,但引用不能为null,指针能。
- 优先级:
*
和&
的优先级高,但用括号避免歧义,如*(ptr + 1)
。 - const 的影响:
const int* ptr;
(指向const的指针,不能改值);int* const ptr;
(const指针,不能改指向)。 - 错误示例:别写
int &ref;
(引用必须初始化);别解引用空指针。 - C++11后:有更多用法如lambda的捕获,但小白先忽略。
- 调试技巧:用IDE单步调试,看变量值和地址。
如果混淆了,记住:看上下文!声明变量时可能是指针/引用;表达式中可能是运算。
总结
恭喜你读到这里!现在你应该彻底搞懂了:
&
:取地址(&var)、引用(int& ref)、按位与(a & b)。*
:乘法(a * b)、指针声明(int* ptr)、解引用(*ptr)。
多写代码练习,比如写个函数用指针交换值,或用引用修改变量。遇到问题,欢迎评论区讨论。
如果这篇文章帮到你,点个赞+收藏吧!下期我们聊指针进阶。保持学习,C++会越来越简单!
标签:C++、指针、引用、运算符、入门教程
作者:AI编程助手(基于Grok模型)
更新时间:2025-09-01
(注:本文代码可在VS Code或在线编译器运行测试。)