在 C++ 中,::
、->
、.
和*
是四种不同的运算符,分别用于不同的上下文场景。它们的详细解释和用法对比:
1. 作用域解析运算符 ::
用途
- 访问 命名空间、类、结构体或枚举 的成员
- 调用 静态成员(变量或函数)
- 区分同名的全局变量和局部变量
示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| #include <iostream>
namespace MyNamespace { int value = 42; }
class MyClass { public: static int staticValue; static void staticMethod() { std::cout << "Static method called!" << std::endl; } };
int MyClass::staticValue = 100;
int main() { std::cout << MyNamespace::value << std::endl;
std::cout << MyClass::staticValue << std::endl; MyClass::staticMethod();
return 0; }
|
关键点
::
不依赖对象实例,直接通过类名或命名空间访问成员。
- 常用于 全局变量、静态成员、嵌套类 等场景。
2. 成员访问运算符 ->
用途
- 通过 指针 访问对象的成员(变量或函数)
- 等价于
(*ptr).member
(先解引用,再用 .
访问)
示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| #include <iostream>
class MyClass { public: int value = 10; void print() { std::cout << "Value: " << value << std::endl; } };
int main() { MyClass obj; MyClass* ptr = &obj;
ptr->value = 20; ptr->print();
return 0; }
|
关键点
->
只能用于指针,不能用于普通对象。
- 在 智能指针(如
std::shared_ptr
)和 迭代器 中也常用。
3. 成员访问运算符 .
用途
- 通过 对象实例(非指针)访问成员(变量或函数)
- 适用于 结构体、类、联合体 等
示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| #include <iostream>
class MyClass { public: int value = 30; void print() { std::cout << "Value: " << value << std::endl; } };
int main() { MyClass obj;
obj.value = 40; obj.print();
return 0; }
|
关键点
.
只能用于对象实例,不能用于指针。
- 在 结构体、类、联合体 中通用。
4. 解引用/指针运算符 *
用途
- 指针声明:表示变量是指针类型
- 解引用:获取指针指向的实际值
- 乘法运算:算术乘法(本文不讨论,因与其他运算符无关)
示例与详解
(1) 指针声明
1 2
| int num = 42; int* ptr = #
|
int* ptr
表示 ptr
存储的是内存地址,而非直接的值。
(2) 解引用(获取指针指向的值)
1 2 3 4 5 6
| int num = 42; int* ptr = #
std::cout << *ptr; *ptr = 100; std::cout << num;
|
(3) 与 ->
的关系
ptr->member
等价于 (*ptr).member
:
1 2 3 4 5 6 7 8 9 10
| class MyClass { public: int value; };
MyClass obj; MyClass* ptr = &obj;
ptr->value = 10; (*ptr).value = 10;
|
四者对比总结
运算符 |
名称 |
适用场景 |
示例 |
:: |
作用域解析符 |
访问命名空间、类静态成员、全局变量 |
MyClass::staticMethod() |
-> |
成员访问(指针) |
通过指针访问对象的成员 |
ptr->value = 10; |
. |
成员访问(对象) |
通过对象实例访问成员 |
obj.value = 10; |
* |
解引用/指针声明 |
1. 声明指针 2. 获取指针指向的值 |
int* ptr; std::cout << *ptr; |
关键区别
*
vs ->
*
是解引用运算符,单独使用时不涉及成员访问。
->
是组合操作:先解引用,再访问成员(即 ->
= *
+ .
)。
::
的特殊性
- 唯一不依赖对象/指针的运算符,直接通过类名或命名空间访问成员。
- 何时用
->
何时用 .
- 对象用
.
,指针用 ->
。
- 智能指针(如
std::shared_ptr
)也使用 ->
。
综合示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| #include <iostream>
namespace MyNamespace { int global = 50; }
class MyClass { public: static int staticVar; int instanceVar = 0; };
int MyClass::staticVar = 100;
int main() { std::cout << MyNamespace::global << std::endl; std::cout << MyClass::staticVar << std::endl;
MyClass obj; MyClass* ptr = &obj; *ptr = MyClass(); std::cout << (*ptr).instanceVar << std::endl;
ptr->instanceVar = 42; obj.instanceVar = 10; std::cout << ptr->instanceVar << " " << obj.instanceVar;
return 0; }
|
常见问题
1. ::
可以访问非静态成员吗?
❌ 不可以。::
只能访问 静态成员、命名空间成员、嵌套类型。
2. *
和 &
的关系?
&
取地址(如 int* ptr = #
)
*
解引用(如 int val = *ptr;
)
- 二者互为逆操作。
4. 什么时候用 ->
,什么时候用 .
?
- 如果变量是 指针(如
MyClass* ptr
),用 ->
。
- 如果变量是 对象(如
MyClass obj
),用 .
。
5. 为什么 ->
不能用于对象?
因为 ->
的设计初衷是简化指针操作((*ptr).member
的语法糖),而对象本身不需要解引用。
6. 智能指针怎么用?
智能指针(如 std::shared_ptr
)也使用 ->
:
1 2 3
| std::shared_ptr<MyClass> ptr = std::make_shared<MyClass>(); ptr->print(); ptr.print();
|
7. 智能指针的 ->
和普通指针有何不同?
无本质区别,只是智能指针(如 std::shared_ptr
)重载了 ->
运算符,行为与原生指针一致:
1 2
| std::shared_ptr<MyClass> smartPtr = std::make_shared<MyClass>(); smartPtr->instanceVar = 30;
|
掌握这四种运算符的差异,能彻底避免 C++ 中的指针和成员访问错误!