为什么要使用C++容器"array"而不是传统的C数组?

4

普遍认为C++数组在几乎相同的效率下更安全。除了检查索引是否超出范围并禁止隐式类型转换为指针外,还有哪些特性?

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

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


C 数组在你试图对它们进行任何有用的操作时几乎立即衰变为指针,一旦你获得了一个指针,就没有干净的方法来获取容器的大小。 - Etienne de Martel
1
std::array 和内置数组一样高效。它的特性是免费的。 - Galik
std::array 可以被视为值,可以被复制,作为参数传递,推理更容易,可以放入容器等。 - alfC
2个回答

8
主要的好处是,一个std::array在C++中是一个一等公民对象,这意味着您可以像使用任何其他“普通”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()有bug,它打印出来的数字比数组中的项数小得多!(原因是函数中的myArray隐式地衰减成指针,因此函数中的sizeof(myArray)计算为sizeof(int*),例如4或8字节,而不是传入数组内容的大小。)


0

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

但现在更加严肃一些 - 通常情况下,隐式转换是编译器根据语言规则执行的,而不会询问程序员是否实际上需要这样做。这就是为什么有时它会导致代码错误(程序员的疏忽或对此类转换发生的情况的错误假设)。

当你进行显式转换时,首先要确保你得到了期望的结果。但更重要的是,如果你的显式转换对编译器来说产生了模糊的结果,甚至在编译器中变成不可能的结果,那么编译器会告诉你,并且你将能够早期修正你的转换决策,从而防止代码中的错误。
因此,显式转换只是一种与编译器更加严格地交流的方式,确保它更好地理解你在编写代码时的意图。作为回报,当你进行错误的转换时(使用隐式转换时,它会按照自己的方式处理,你甚至不知道这样的转换效果与你想要的有所不同),编译器会给你提示。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接