提问人:Deepak 提问时间:2/16/2023 最后编辑:phuclvDeepak 更新时间:2/16/2023 访问量:76
为什么 cin 没有像 scanf() 在 C 中那样具有 & 运算符或说明符格式?
Why doesn't cin have ampersand operator or specifier format like scanf() does in C?
问:
就像我在学习 C++ 动态内存分配时遇到了这个疑问,现在再也无法专注于学习它了。:(
int n;
cout << "Enter array size: ";
cin >> n;
int *p = new int[n];
所以到目前为止一切都很好,我只是在堆区域分配了 n 个 int 内存块
现在,在使用 for 循环获取输入时,当我尝试将 p[i] 写为*(p+i)
for (int i = 0; i < n; i++)
{
// cin >> p[i]; // This is correct
// cin >> *(p+i); // This is correct
cin >> (p + i); // same as cin >> &p[i], right? Now, this gives me error since I didn't deference
// it and now I'm confused as to why we need to deference it? *(p+i) tells which
// block the value is to be stored in, but doesn't (p+i) also give us the same
// address? The input value should still have been stored in the respective memory
// block, right? But it doesn't and I can't visualize it why?
// Also, now I'm even confused as to why writing cin >> n works and writing cin >> &n doesn't??
}
我只是期望我的值仍然应该被接受到相应的数组元素中,但事实并非如此,相反,它给了我一个非常错误的错误,我无法理解。
我试图寻找答案,但仍然不清楚概念的可视化和清晰度。到目前为止,我所知道的是 cin 是 istream 类的一个对象,运算符与 cin 一起使用时有点像函数调用,我们在 >> 运算符之后写的变量名称是“通过引用传递”或类似的东西,这似乎就是为什么我们可能不给出地址,因为引用变量默认已经有它, 但我不确定,仍然有疑问。>>
请有人以适当的顺序和适当的例子解释它。我将不胜感激。
答:
is 的类型和 is 的类型。对于第一个,您正在读取一个整数,所以这很清楚。*(p + i)
int
(p + i)
int*
为什么不看?当函数通过引用获取参数时,参数必须完全相同。你给它,所以它会尝试阅读.cin >> (p + i)
int
int*
int*
我们将如何阅读指针?我想我们可以读取一个整数并将其分配给指针变量。我们目前正在读取临时值。 需要一个引用,它无法获取临时值,这就是您收到编译错误的原因。p + i
operator>>
让我们通过使用另一个变量来跳过这个问题:
int* pi = p + i;
cin >> pi;
这仍然无法编译,因为读取 void*
存在过载,但不会。在 C++ 中,不能在两种指针类型之间自动转换。如果你想读取 ,你可以这样做,但你必须为 编写一个重载。int*
int*
operator>>
评论
*(p + i)
int&
int
我们在 >> 运算符之后写入的变量名称是“通过引用传递”
这正是重点。C语言的主要目标之一是构建一个能够提供高效代码的相当简单的编译器。因此,它试图保持尽可能的显式,只允许将参数作为值传递给函数。如果你想修改一个函数中的某些东西,你只需传递一个指向它的指针。
C++语言的目标是更高的层次。正确的指针处理并不总是微不足道的,内存分配也并非易事。C++ 的理念是,这些都是血腥的细节,应该隐藏在高级程序中。出于这个原因,许多 SO 用户建议永远不要使用 and(显式分配),而是依赖能够正确处理自动解除分配的子化以及复制和移动语义的容器。new[]
delete[]
出于同样的原因,在语言中引入了引用。乍一看,它们看起来只是老式 C 程序员的伪装指针,这意味着无用的语法 suger,更糟糕的是,与需要指针来修改函数变量的 C 习语相矛盾(实际上确实在较低级别)。但这正是它们的用途:您可以直接对变量执行操作,而无需显式取消引用它,从而消除了忘记代码中某处的风险。operator <<
*
实际上,流提取器的签名是:
istream& operator << (istream& in, int& val);
因此,该函数能够修改流本身和传递的变量。
评论
cin >> p[i]