问题描述
流行的观点是 C++ 数组更安全,效率几乎相同。除了检查索引是否超出范围和不允许隐式类型转换为指针之外,还有其他功能吗?
此外,为什么传统 C 数组的隐式类型转换被认为是一种不好的方式?
我不太擅长 C++(也不太擅长英语),如果这个问题不值得回答,请原谅我。谢谢!
解决方法
主要的好处是 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 个字节,而不是传入数组的内容)
不确定您关于 C 数组隐式转换的问题的确切含义,但我猜您的意思是隐式转换存储在其中的值(如 int a[10]; float f=a[0]
中),或转换隐式指针到第一个元素(如 int a[10]; void* p=a;
)。无论如何,隐式地将任何指向 void*
指针的指针都可以(如果你想读取它,你只需要知道存储在这样的指针上的内存大小是多少),因为 void*
指针不是真正用于数据操作,因此无论何时使用 void*
指针,您都知道自己在做什么,对吗?
但现在更严肃一点 - 通常,隐式转换是编译器根据语言规则执行的操作,而不会询问程序员它是否是实际需要的。这就是为什么它有时会导致代码中的错误(程序员的疏忽,或对此类演员期间发生的事情的错误假设)。
当您显式转换时,首先要确保获得所需的结果。但更重要的是,如果您的显式转换为编译器提供了模棱两可的结果,甚至编译器无法实现,那么编译器会通知您,您将能够及早修改您的转换决策并防止错误在您的代码中。
所以显式转换只是一种更严格地与编译器对话的方式,确保它在您编写代码时更好地理解您的意思。然后,作为回报,编译器会在您错误地转换某些内容时给您提示(使用隐式转换,它会按自己的方式做事,您甚至不知道这种转换的效果何时与您想要的不同)。>