【问题标题】:Why use C++ container "array" rather than traditional C array?为什么使用 C++ 容器“数组”而不是传统的 C 数组?
【发布时间】:2021-07-11 23:53:09
【问题描述】:

普遍认为 C++ 数组更安全,效率几乎相同。除了检查索引是否超出范围和不允许隐式类型转换为指针外,还有其他功能吗?

另外,为什么传统C数组的隐式类型转换被认为是一种不好的方式?

我不太擅长 C++(英文也是),如果这个问题不值得回答,请原谅我。谢谢!

【问题讨论】:

  • C 数组在你尝试对它们做任何有用的事情时几乎立即衰减为指针,一旦你得到一个指针,你就无法获得容器的大小。
  • std::array内置 数组一样高效。它的功能是免费的。
  • std::array 可以被视为一个值,它们可以被复制,作为参数传递,推理变得更容易,可以放入容器等。

标签: c++ c++11 stl containers


【解决方案1】:

主要的好处是 std::array 在 C++ 中是 first-class object,这意味着您可以用它做所有其他“普通”C++ 对象可以做的事情。

另一方面,传统的 C 数组不是一流的对象,这意味着很多事情都行不通:

#include <array>

// Works!
std::array<int, 5> ReturnAStdArrayOfSixes()
{
   std::array<int, 5> ret;
   ret.fill(6);
   return ret;
}

// Doesn't compile, sorry
int[5] ReturnACArrayOfSixes()
{
   int ret[5];
   for (int i=0; i<5; i++) ret[i] = 6;
   return ret;
}

int main(int, char **)
{
   std::array<int, 5> stdArray1;
   std::array<int, 5> stdArray2;

   int cArray1[5];
   int cArray2[5];

   stdArray1 = stdArray2;  // works
   cArray1 = cArray2;  // error: array type 'int [5]' is not assignable

   if (stdArray1 < stdArray2) {/* do something */}  // compares arrays' contents lexographically
   if (cArray1 < cArray2) {/* do something */}      // compiles, but compares pointers which probably isn't what you wanted

   return 0;
}

至于“传统 C 数组的隐式类型转换”(我认为你的意思是数组类型隐式衰减为指针类型),这是一个有用的机制,但如果你不是,它会咬你期待它,例如:

// This code works as expected
int myArray[5];
cout << "There are " << (sizeof(myArray)/sizeof(int)) << " items in myArray\n";

现在让我们将上面的代码重构为一个不错的函数,以便我们可以重用它:

void PrintArraySize(int myArray[5])
{
   std::cout << "There are " << (sizeof(myArray)/sizeof(int)) << " items in myArray\n";
}

int main(int, char **)
{
   int myArray[5];
   PrintArraySize(myArray);
   return 0;
}

...哦,不!现在 PrintArraySize() 有问题,并且打印的数字远小于数组中的项目数! (原因是函数中的myArray已经隐式衰减为指针,所以函数中的sizeof(myArray)求值为sizeof(int *),例如4或8个字节,而不是传入的内容的大小数组)

【讨论】:

    【解决方案2】:

    不确定您关于 C 数组的隐式转换的问题究竟是什么意思,但我猜您的意思是隐式转换存储在其中的值(如在 int a[10]; float f=a[0] 中),或者将隐式指针转换为第一个元素(如int a[10]; void* p=a;)。无论如何,隐式转换任何指向 void* 指针的指针是可以的(如果你想读取它,你只需要知道存储在该指针处的内存大小是多少),因为 void* 指针并不真正用于数据操作,所以每当你使用void* 指针时,你就知道自己在做什么,对吧?

    但现在更严肃一点 - 隐式转换通常是编译器根据语言规则执行的操作,而无需询问程序员它是否是真正需要的。这就是为什么它有时会导致代码错误(程序员的疏忽,或者对这种转换过程中发生的事情的错误假设)。

    当您显式转换时,首先,您要确保获得所需的结果。但更重要的是,如果您的显式转换为编译器提供了模棱两可的结果,甚至编译器无法证明,那么编译器会通知您,您将能够及早修改您的转换决策并防止错误在你的代码中。

    因此,显式转换只是一种更严格地与编译器对话的方式,以确保它更好地理解您在编写代码时的意思。然后,作为回报,当您错误地转换某些内容时,编译器会为您提供提示(使用隐式转换,它会以自己的方式做事,您甚至不知道这种转换的效果何时与您想要的不同)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-16
      • 1970-01-01
      • 2014-03-06
      • 2015-08-22
      • 2021-05-07
      相关资源
      最近更新 更多