c++ - "char[]"是正确的类型吗?

标签 c++ arrays templates c++11

昨天,我惊讶地发现一些代码似乎将 char[] 视为一种类型:

typedef std::unique_ptr<char[]> CharPtr;

以前,我会这样写:

typedef std::unique_ptr<char*, CharDeleter> CharPtr;
// Custom definition of CharDeleter omitted

经过一些研究,我发现 char[] 语法是有效的,因为 std::unique_ptr 提供了一个模板专门化来处理数组(例如,它会自动调用 delete[] 用于数组而不需要自定义删除器)

但是 char[] 在 C++ 中究竟意味着什么?

我见过这样的语法:

const char a[] = "Constant string"; // Example 1

char *p = new char[5]; // Example 2

bool foo(char param[10]); // Example 3

我是这样解释这些例子的:

示例 1 分配了一个静态数组(在堆栈上)并且空索引是有效的,因为字符串的真实大小在编译时是已知的(例如,编译器基本上在幕后为我们处理长度)

示例 2 动态分配 5 个连续字符,第一个字符存储在 p 中存储的地址。

示例 3 定义了一个将大小为 10 的数组作为参数的函数。 (在幕后,编译器将数组视为指针)——例如这是一个错误:

void foo(char test[5]) {}
void foo(char * test) {}

因为函数签名对编译器来说是不明确的。

我觉得我了解数组/指针的差异和相似之处。我的困惑可能源于我缺乏构建/阅读 C++ 模板的经验。

我知道模板特化基本上允许根据模板类型参数使用自定义模板(基于特定模板)。 char[] 只是一种可用于模板特化(调用特定特化)的语法吗?

此外,像 char[] 这样的数组“类型”的正确名称是什么?

最佳答案

What does char[] actually mean in C++?

让我们找出答案:

[C++11: 8.3.4/1]: In a declaration T D where D has the form

   D1 [ constant-expressionopt] attribute-specifier-seqopt

and the type of the identifier in the declaration T D1 is “derived-declarator-type-list T”, then the type of the identifier of D is an array type; if the type of the identifier of D contains the auto type-specifier, the program is ill-formed. T is called the array element type; this type shall not be a reference type, the (possibly cv-qualified) type void, a function type or an abstract class type. If the constant-expression (5.19) is present, it shall be an integral constant expression and its value shall be greater than zero. The constant expression specifies the bound of (number of elements in) the array. If the value of the constant expression is N, the array has N elements numbered 0 to N-1, and the type of the identifier of D is “derived-declarator-type-list array of N T”. An object of array type contains a contiguously allocated non-empty set of N subobjects of type T. Except as noted below, if the constant expression is omitted, the type of the identifier of D is “derived-declarator-type-list array of unknown bound of T”, an incomplete object type. The type “derived-declarator-type-list array of N T” is a different type from the type “derived-declarator-type-list array of unknown bound of T”, see 3.9. [..]

正如您所指出的,这些“未知边界数组”正在通过 std::unique_ptr 特化使用。

关于示例 1,虽然在 [C++11: 8.5.5] 中出人意料地不清楚,但带有初始化程序的 char[] 是一种特殊情况,未涵盖通过上面的文字:a 实际上是一个const char[16]。所以,是的,“编译器基本上在幕后为我们处理长度”。


Example 3 defines a function that takes an array of size 10 as a parameter. (Behind the scenes the compiler treats the array like a pointer)

差不多。事实上,没有任何关于它的“幕后”:转换在手册中。它是首要的、明确的和标准化的。

所以:

-- e.g. it is an error to have:

void foo(char test[5]) {}
void foo(char * test) {}

because the function signatures are ambiguous to the compiler.

事实上,这不是由于“歧义”造成的错误,而是因为您确实定义了同一个函数两次。

关于c++ - "char[]"是正确的类型吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29172362/

相关文章:

c++ - 返回的对象失去属性

c++ - 如何使用 MFC 获取单独窗口的句柄?

c++ - 从 cpp 传递到 CUDA 时矩阵显示为空

javascript - angularJS 模板,正确使用指令或替代方案?

c++ - C++ 中 move 时内存中发生了什么

c++ - 为什么同一个对象的析构函数被调用了两次?

java - 为什么我的数组类无法找出随机生成的数组的最小值和最大值?

arrays - 一种将数组拆分为三分之二并显示给用户的干净方法

c++ - 模板 lambda 与带有模板 operator() 的仿函数

c++ - 一个 Debug-Print 函数来控制它们