c/c++中的-->运算符

本文揭示了C/C++中看似神秘的'-->'操作符的真实面目,其实它只是两个常见操作符的巧妙组合,即自减运算符--和大于比较运算符>。通过实例解析,帮助读者深入理解这一不为人熟知的编程技巧。

参考What is the name of this operator: “–>”?

c/c++中以下代码是合法的:

#include <stdio.h>
int main()
{
     int x = 10;
     while( x --> 0 ) // x goes to 0
     {
        printf("%d ", x);
     }
}

-->是一个合法的操作符,我打赌自认c/c++熟手的你们都不知道这个操作符。有人称它为goes to操作符,x-->0表示x向0趋近

其实我在忽悠你们。 并且我相信有很多人对此把戏相当熟悉。没错,-->只是两个操作符恰好遇在了一起,他们是自减运算符--和大于比较运算符>

while (x-- > 0)
    ...

类似的把戏还有:

while (x -- \
             \
              \
               \
                > 0)
    printf("%d ", x);

原文地址:http://codemacro.com/2012/09/03/goes-to-operator/ 
written byKevin Lynx posted athttp://codemacro.com

<think> 我们被要求回答关于C++运算符 -> 或 ->* 应用于非指针类型的问题及解决办法。 根据引用资料,用户提供的引用主要讨论了指针的基本操作(*和&),以及成员指针运算符(->)的简单示例(引用[5]提到了成员指针运算符,但仅展示了通过指针访问结构体成员)。 但是,用户的问题是关于“-> 或 ->* 应用于非指针类型”的问题及解决方案。这意味着我们需要解释当这些运算符被用于非指针类型时会发生什么,以及如何解决这类问题。 首先,我们需要明确: 1. `->` 运算符:通常用于指针访问对象的成员。例如,如果有一个指向对象的指针ptr,则可以使用ptr->member来访问成员。 2. `->*` 运算符:用于通过指向成员的指针来访问对象的成员。例如,如果有一个指向类成员的指针ptr_mem,则可以使用obj->*ptr_mem(如果obj是指针)或obj.*ptr_mem(如果obj是对象)来访问。 问题:当这些运算符应用于非指针类型时,编译器会报错。 常见错误场景: 1. 对一个非指针类型的变量使用`->`运算符。 例如:有一个对象(不是指针)obj,却试图使用obj->member。 2. 对一个非指针类型的变量使用`->*`运算符。 解决方案: 1. 对于`->`运算符:确保左侧操作数是一个指针类型。如果是一个对象实例,应该使用`.`运算符。 错误示例: MyClass obj; obj->member; // 错误:obj不是指针 正确做法: MyClass obj; obj.member; // 使用点运算符 或者,如果确实需要指针,则应该使用指针: MyClass *ptr = &obj; ptr->member; 2. 对于`->*`运算符:同样,左侧操作数必须是指针。如果是一个对象,应该使用`.*`运算符。 错误示例: MyClass obj; int MyClass::*ptr_mem = &MyClass::member; // 指向成员的指针 obj->*ptr_mem; // 错误:obj不是指针 正确做法: obj.*ptr_mem; // 使用.*运算符 // 或者使用指针 MyClass *ptr = &obj; ptr->*ptr_mem; 另外,需要注意的是,`->*`运算符的左侧操作数可以是指向对象的指针,而右侧操作数是指向该对象成员的指针(包括数据成员和成员函数)。 总结: 运算符的使用必须与操作数的类型匹配: - 对于对象实例(非指针),使用`.`和`.*`。 - 对于对象指针,使用`->`和`->*`。 因此,当出现将`->`或`->*`应用于非指针类型时,解决方案就是检查左侧操作数的类型,如果是对象实例则改为使用`.`或`.*`;如果确实需要用指针访问,则先将对象地址赋给指针变量,再通过指针访问。 下面我们用一个代码示例来说明: ```cpp #include <iostream> using namespace std; class MyClass { public: int member; void print() { cout << "member = " << member << endl; } }; int main() { MyClass obj; // 错误用法: // obj->member = 10; // 错误:'obj'不是指针 // 正确用法(使用点运算符): obj.member = 10; obj.print(); // 使用指针 MyClass *ptr = &obj; ptr->member = 20; ptr->print(); // 指向成员的指针 int MyClass::*p_member = &MyClass::member; // 错误用法: // obj->*p_member = 30; // 错误:'obj'不是指针 // 正确用法(使用.*运算符): obj.*p_member = 30; obj.print(); // 正确用法(使用->*运算符): ptr->*p_member = 40; ptr->print(); return 0; } ``` 在上面的代码,我们展示了错误用法(注释掉的部分)和正确用法。 如果用户遇到此类错误,编译器通常会给出明确的错误信息,例如“left operand has type 'MyClass' but requires pointer type”。根据错误信息,用户应该检查左侧操作数的类型。 因此,解决办法就是根据左侧操作数的类型选择正确的运算符: - 对象:使用`.`和`.*` - 指针:使用`->`和`->*` 这样就能解决运算符应用于非指针类型的问题。 </think>### C++运算符 `->` 或 `->*` 应用于非指针类型的问题及解决方案 在 C++ ,`->` 和 `->*` 是专门用于**指针类型**的运算符。当它们被错误地应用于非指针类型时,会导致编译错误。以下是详细分析和解决方案: --- ### 问题原因分析 1. **运算符用途**: - `->`:通过指针访问对象的成员(等价于 `(*ptr).member`) - `->*`:通过指针访问成员指针指向的成员(等价于 `(*ptr).*member_ptr`) 2. **错误场景**: ```cpp struct Student { int age; }; Student s; s->age; // 错误:s 是对象而非指针 ``` 编译器报错:`error: base operand of '->' has non-pointer type 'Student'` --- ### 解决方案 #### 方法 1:正确使用运算符类型 - **对象实例**用 `.` 或 `.*` - **对象指针**用 `->` 或 `->*` ```cpp Student s; Student* ptr = &s; // 正确声明指针 // 访问成员 s.age = 18; // 对象用 . ptr->age = 20; // 指针用 -> // 成员指针访问 int Student::*age_ptr = &Student::age; s.*age_ptr = 22; // 对象用 .* ptr->*age_ptr = 25; // 指针用 ->* ``` #### 方法 2:重载运算符(高级用法) 若需自定义类型支持 `->`,可重载 `operator->()`: ```cpp class Wrapper { Student* ptr; public: explicit Wrapper(Student* p) : ptr(p) {} Student* operator->() { return ptr; } // 重载 -> }; Wrapper w(&s); w->age = 30; // 合法:w.operator->() 返回指针 ``` #### 方法 3:智能指针的自动转换 使用 `std::unique_ptr`/`std::shared_ptr` 自动支持 `->`: ```cpp auto ptr = std::make_unique<Student>(); ptr->age = 35; // 智能指针隐式支持 -> ``` --- ### 常见错误案例及修复 | **错误代码** | **错误原因** | **修复代码** | |----------------------|---------------------------|---------------------| | `Student s; s->age;` | 对象误用 `->` | `s.age;` | | `int (Student::*mem_ptr) = &Student::age; s->*mem_ptr;` | 对象误用 `->*` | `s.*mem_ptr;` | | `Student* p = nullptr; p->age;` | 空指针解引用(运行时崩溃) | 检查 `if (p) p->age;` | --- ### 关键总结 1. **类型匹配**: ```mermaid graph LR A[操作数类型] --> B[对象实例] A --> C[对象指针] B --> D[使用 . 或 .*] C --> E[使用 -> 或 ->*] ``` 2. **编译检查**:开启编译器警告(如 `-Wall`)可提前捕获此类错误。 3. **语义清晰**:成员指针(`->*`)需配合指向类成员的指针使用,常规开发较少见。 > 遵循这些规则可避免 95% 以上的相关错误。若需深入理解成员指针机制,建议结合 C++ 的 _Pointer-to-Member_ 特性系统学习[^3][^5]。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值