为何cin无需像scanf那样使用取址符或格式说明符?附代码疑问
关于C++中cin >>运算符的疑问解答
核心原理:std::cin的>>运算符重载规则
std::cin是std::istream类的实例,>>运算符的行为完全依赖于标准库提供的重载版本:
- 对于基本数据类型(如int、float等),对应的重载是:
std::istream& operator>>(std::istream&, T&)(T为基本类型)。这个版本要求传入一个可修改的左值引用,目的是让cin能把读取的值直接写入到目标变量的内存中。 - 仅对
char*类型提供了特殊重载:std::istream& operator>>(std::istream&, char*),用于读取C风格字符串到指定的字符数组中。
问题1:为什么cin >> (p+i)报错,而cin >> p[i]/cin >> *(p+i)可行?
先明确各个表达式的类型:
p[i]和*(p+i):两者完全等价,都是int类型的左值(指向堆上第i个int元素的内存位置,可被修改)。它们能直接匹配operator>>(istream&, int&)重载,cin会把读取的值写入到这个内存位置,所以写法正确。p+i:这是一个int*类型的右值(计算出来的是指向第i个int元素的地址值,但本身是一个临时的指针值)。标准库没有为int*类型提供>>运算符重载,编译器找不到匹配的函数,因此报错。
你误以为cin >> (p+i)等同于cin >> &p[i],但实际上&p[i]也是int*类型,同样没有对应的重载,所以这个写法也会报错——你的这个假设本身就是错误的,&p[i]并不能用来给cin传参。
问题2:为什么cin >> n可行,而cin >> &n不行?
n是int类型的左值,能绑定到int&,匹配operator>>(istream&, int&)重载,cin可以直接把输入值写入n的内存,所以可行。&n是int*类型的指针值,同样没有对应的>>重载,编译器无法找到匹配的函数,因此报错。
验证示例
#include <iostream> using namespace std; int main() { int n = 3; int* p = new int[n]; // 正确写法:传入int& for (int i = 0; i < n; i++) { cin >> p[i]; // 等价于 cin >> *(p+i); } // 错误写法:传入int*,无对应重载 // for (int i = 0; i < n; i++) { // cin >> (p + i); // 编译报错 // cin >> &p[i]; // 同样编译报错 // } // 输出验证 for (int i = 0; i < n; i++) { cout << p[i] << " "; } delete[] p; return 0; }
如果非要用指针地址的方式传入cin,你可以把指针解引用,转换成int&:
cin >> *(p + i); // 这就是正确的写法,本质是把int*转换成int&
内容的提问来源于stack exchange,提问作者Deepak
相关产品推荐
相关产品推荐

