【问题标题】:Comparing arrays for equality in C++在 C++ 中比较数组是否相等
【发布时间】:2012-10-03 16:51:54
【问题描述】:

有人可以向我解释一下为什么以下代码的输出显示数组不等于

int main()
{

    int iar1[] = {1,2,3,4,5};
    int iar2[] = {1,2,3,4,5};

    if (iar1 == iar2)
        cout << "Arrays are equal.";
    else
        cout << "Arrays are not equal.";

    return 0;   
}

【问题讨论】:

  • 使用std::arraystd::vector。 C 数组没有单一的优势,它们只会带来痛苦和悲伤。没有任何借口。
  • @daknøk 与 C 的互操作怎么样?
  • @weberc2 .data()。没有任何借口。
  • 不,它没有,但它用于 C 互操作。不,将 C 数组转换为 std::arrays,只是为了检查是否相等,是完全不可接受的。它涉及复制。当std::array_view 成为标准时,我们将有一种明智的方式来比较由 C 互操作产生的原始数组。
  • 您声明的变量是指向内存中两个不同位置的两个单独数组中的第一个 int 元素的指针。它们不相等(地址不同),因此条件测试评估为假。

标签: c++ arrays comparison equality


【解决方案1】:
if (iar1 == iar2)

这里iar1iar2 正在衰减 指向各自数组的第一个元素的指针。由于它们是两个不同的数组,因此指针值当然是不同的,并且您的比较测试也不相等。

要进行逐元素比较,您必须编写一个循环;或者改用std::array

std::array<int, 5> iar1 {1,2,3,4,5};
std::array<int, 5> iar2 {1,2,3,4,5};

if( iar1 == iar2 ) {
  // arrays contents are the same

} else {
  // not the same

}

【讨论】:

  • +1 表示唯一带有“衰减”一词的答案(或其他任何明确表示的答案)。
  • "...你必须要么写一个循环...." 最好使用 std::equal。不要偏离您的观点,即使用原始数组是主要问题。
  • 对于像我这样在尝试使用 std::array 时得到类似“未定义模板的隐式实例化...”的人,请尝试 #import 或 #include 。跨度>
  • “衰变”的好解释:stackoverflow.com/a/1461449/108238
【解决方案2】:

由于还没有人提及,您可以将数组与std::equal 算法进行比较:

int iar1[] = {1,2,3,4,5};
int iar2[] = {1,2,3,4,5};

if (std::equal(std::begin(iar1), std::end(iar1), std::begin(iar2)))
    cout << "Arrays are equal.";
else
    cout << "Arrays are not equal.";

您需要包含&lt;algorithm&gt;&lt;iterator&gt;。如果你还没有使用 C++11,你可以这样写:

if (std::equal(iar1, iar1 + sizeof iar1 / sizeof *iar1, iar2))

【讨论】:

  • 一个有趣的事实是,即使 iar2 是 {1,2,3,4,5,6},上述条件仍然成立。
  • 这一点的美妙之处在于,如果有一天您恢复理智并想要转换代码以使用它们而不是 C 数组,那么完全相同的语法也适用于 std::vectorstd::array
  • 如果iar1 大于iar2,如何避免超出iar2 的末尾?你不应该在那里传递std:end(iar2)吗?
  • 是的,您应该使用 4 参数重载! std::equal(std::begin(iar1),std:end(iar1),std:begin(iar2),std:end(iar2);
【解决方案3】:

您不是在比较数组的内容,而是在比较数组的地址。因为它们是两个独立的数组,所以它们有不同的地址。

通过使用更高级别的容器(例如std::vectorstd::dequestd::array)来避免此问题。

【讨论】:

  • 需要注意的是,这些容器已经实现了自己的 == 运算符来执行此检查。
【解决方案4】:

数组不是原始类型,数组在C++内存中属于不同的地址

【讨论】:

    【解决方案5】:

    没有人提到memcmp?这也是一个不错的选择。

    /* memcmp example */
    #include <stdio.h>
    #include <string.h>
    
    int main ()
    {
      char buffer1[] = "DWgaOtP12df0";
      char buffer2[] = "DWGAOTP12DF0";
    
      int n;
    
      n=memcmp ( buffer1, buffer2, sizeof(buffer1) );
    
      if (n>0) printf ("'%s' is greater than '%s'.\n",buffer1,buffer2);
      else if (n<0) printf ("'%s' is less than '%s'.\n",buffer1,buffer2);
      else printf ("'%s' is the same as '%s'.\n",buffer1,buffer2);
    
      return 0;
    }
    

    参考:http://www.cplusplus.com/reference/cstring/memcmp/

    【讨论】:

    • 这段代码的逻辑问题是memcpm中的sizeof(buffer1)
    • 不正确。 memcmp 比较内存是否相等而不是数组。可以填充数组中的值并用随机数据填充间隙,在这种情况下,memcmp 将报告内存不同,尽管数组相等。这是一个对我来说打印“内存不相等,数组相等”的示例:godbolt.org/z/fedW7veYn
    • @ElvissStrazdins 感谢您的代码...顺便说一句,我认为这是由结构对齐引起的,对吧?一旦我通过 attribute ((packed)) 禁用对齐,内存和数组都是相等的。
    【解决方案6】:

    如果您不愿意将现有代码更改为 std::array,请使用几种方法来代替 non-type template arguments

    //Passed arrays store different data types
    template <typename T, typename U, int size1, int size2>
    bool equal(T (&arr1)[size1], U (&arr2)[size2] ){
        return false;
    }
    
    //Passed arrays store SAME data types
    template <typename T, int size1, int size2>
    bool equal(T (&arr1)[size1], T (&arr2)[size2] ){
        if(size1 == size2) {
            for(int i = 0 ; i < size1; ++i){
                if(arr1[i] != arr2[i]) return false;
            }
            return true;
        }
        return false;
    }
    

    这里是demo。请注意,在调用时,我们只需要传递数组变量,例如equal(iar1, iar2) 在你的情况下,不需要传递数组的大小。

    【讨论】:

      【解决方案7】:

      您正在比较地址而不是值。

      【讨论】:

        【解决方案8】:

        两者都将内存地址存储到两个不同数组的第一个元素。这些地址不能相等,因此输出。

        【讨论】:

        • 几乎是正确的@Vachaspati——它们可能相等(例如,在命令iar1 = iar2; 之后),但在这种情况下,在初始化之后,它们不会相等。
        【解决方案9】:

        没错。在大多数中,如果不是所有的 C 实现,数组标识符可以隐式转换为指向第一个元素的指针(即第一个元素的地址)。您在这里所做的是比较这些地址,这显然是错误的。

        相反,您需要遍历两个数组,检查每个元素。如果你在没有失败的情况下完成了两者,它们是平等的。

        【讨论】:

        • none 中是数组标识符,实际上是第一个元素的地址。数组标识符实际上就是数组。在int arr[6] 中,arr 指的是int[6] 类型的值。该值可隐式转换为int*,其值为&amp;arr[0](通常称为衰减)。但数组并不是“实际上”的指针。
        【解决方案10】:

        当我们使用数组时,我们实际上是在使用指向数组中第一个元素的指针。因此,if( iar1 == iar2 ) 这个条件实际上比较了两个地址。这些指针指向的不是同一个对象。

        【讨论】:

          【解决方案11】:

          如果你愿意使用std::array而不是内置数组,你可以使用:

          std::array<int, 5> iar1 = {1,2,3,4,5};
          std::array<int, 5> iar2 = {1,2,3,4,5};
          
          if (iar1 == iar2)
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2023-03-11
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2015-03-13
            相关资源
            最近更新 更多