【问题标题】:Array Assignment数组赋值
【发布时间】:2011-03-11 22:32:17
【问题描述】:

让我用一个例子来解释-

#include <iostream>

void foo( int a[2], int b[2] ) // I understand that, compiler doesn't bother about the
                               // array index and converts them to int *a, int *b
{
    a = b ;  // At this point, how ever assignment operation is valid.

}

int main()
{
    int a[] = { 1,2 };
    int b[] = { 3,4 };

    foo( a, b );

    a = b; // Why is this invalid here.

    return 0;
}

是不是因为数组在传递给函数foo(..)时会衰减为指针,所以可以进行赋值操作。而在main 中,是不是因为它们的类型为int[],它使赋值操作无效。 a,b 在这两种情况下不是意味着相同吗?谢谢。

编辑 1:

当我在函数foo 中执行此操作时,它会将b's 起始元素位置分配给a。所以,考虑到它,是什么让语言开发人员在main() 中没有做同样的事情。想知道原因。

【问题讨论】:

  • sizeof(a) 在这些位置不同的原因相同:我不知道 :)
  • 数组到指针的转换很棘手。如果您愿意,请阅读:c-faq.com/aryptr/index.html
  • 不要在 C++ 中使用数组,除非你有充分的理由这样做。 std::vector&lt;&gt; 几乎可以满足您的所有需求。
  • @David Thornley - 只是出于好奇问了这个问题,这与另一篇帖子有点相关stackoverflow.com/questions/5278540/…
  • 相关FAQ

标签: c++ arrays


【解决方案1】:

您回答了自己的问题。

因为这些

int a[] = { 1,2 };
int b[] = { 3,4 };

类型为int[2]。但是这些

void foo( int a[2], int b[2] )

类型为int*

你可以复制指针,但不能复制数组。

【讨论】:

  • 另外值得注意的是,函数内部的a = b并不影响函数外部的实际数组。
  • 顺便说一句,要使用数组实现复制语义,一种可能的解决方案是将它们包装在struct 或类中:默认的复制构造函数和赋值运算符可以解决问题。但在这种情况下,您可能希望直接使用std::array 模板。
  • @ybungalobill - 当我在函数foo 中执行此操作时,它将b's 起始元素位置分配给a。因此,考虑到它,是什么让语言开发人员在main() 中没有做同样的事情。想知道原因。谢谢。
  • @Matteo:更好:使用 std::vector。
  • @Mahesh:这种语法来自 C,而 C 语言开发人员认为 C 是一组用于汇编的宏,所以从他们的角度来看,这些只是指针。请注意,main 中不涉及指针,因此没有可复制的内容,而 f 接收指针作为机器级别的参数。
【解决方案2】:

答案在“按值传递”的概念中,这意味着被调用的函数接收参数的副本——它们是指向整数的指针。所以ab 是这些指针的本地副本(调用者中不存在它们;它们是数组转换的结果,即它们的第一个元素的地址)。如果你写了也没什么不同

void foo( int aparam[2], int bparam[2] )
{
    int* a = aparam;
    int* b = bparam;

    a = b ;
}

Dennis Ritchie 承认参数的数组语法是语言上的一个缺陷,它只是为了简化 B 程序的转换——古老的历史!它还对 C++ 的设计产生了有害影响,因为数组不能按值传递。这种语法一直是混乱的根源。所以... 不要使用它;假装不合法。如果每个人都这样做,它可能会逐渐消失,并且可能在几十年后被赋予适当的语义。

更新:有关按值调用(C 和 Java 中唯一的调用形式;请参阅下面的我的 cmets)、按引用调用(在 C++ 中添加)和其他评估策略,见http://en.wikipedia.org/wiki/Evaluation_strategy

【讨论】:

  • 当传递数组时,按值传递 不是一个正确的术语。它的引用传递
  • @Mahesh 你大错特错了。数组可以像其他任何东西一样通过引用或值传递。您不熟悉可以按值传递数组的语言这一事实​​并不意味着它们不能。如果不是因为 C 数组参数是指针 botch,很有可能在堆栈上传递小数组,就像可以在堆栈上传递结构一样。如果您仔细考虑一下,这一点就很明显了。
  • @Mahesh P.S.人们很容易被以下事实混淆:在 Java 等语言中,引用是按值传递的,这是一个纯按值传递的系统,或者在 C 中是通过指针传递。按值传递引用与按引用传递完全不同。有关这一点的详细讨论,请参阅javadude.com/articles/passbyvalue.htm
【解决方案3】:

在主函数中
a 和 b 是常量指针,实际上它们是第一个元素的地址。它们就像 l 值。你不能复制到左值,但你可以改变它们指向的整数的值。

在 foo 函数中
a 和 b 是指针。这样您就可以更改它们的值。

【讨论】:

  • ab 是主函数中的不是常量指针,它们是数组。指针和数组不是一回事。最明显的区别是sizeof(a)a+n 的值不是a 是指针时的值。
  • 数组不是指针——阅读标准。我不知道你的等式应该表示什么,但int a[2] 分配在堆栈上并在退出范围时被销毁,而new int[] 在堆上......而你的第二个a 是一个数组指向int 的指针。
  • 数组是常量指针。 “int a[2]”与“int const * a[] = new int[2]”相同。关于 sizeof,这是因为编译器会跟踪所有数组并在其中进行不同的处理
  • @jim,只是为了澄清。我知道 int a[] 将在堆栈中分配,而 int const * a[] = new int[2] 将在堆中..这是c ++中的一个基本概念......我只是想简化原因。反正认为
猜你喜欢
  • 2016-01-17
  • 2011-05-06
  • 2011-12-22
  • 1970-01-01
  • 2014-07-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-12-17
相关资源
最近更新 更多