关于T[]作为模板参数的疑问:unique_ptr<T[]>与unique_ptr<T[3]>的区别
unique_ptr<T[]> and Array Types in C++ Great question! Array types in C++ have some subtle behaviors that can trip up even experienced developers, especially when paired with smart pointers. Let's unpack your questions one by one.
1. What is the type T[] in the template?
T[] is an incomplete array type in C++. Unlike fixed-size arrays (like T[3]), it doesn't have a compile-time known size. When used as a template argument for unique_ptr, this specialization (std::unique_ptr<T[]>) is explicitly designed to manage dynamically allocated arrays—meaning memory allocated with new T[].
The critical detail here is its default deleter: std::default_delete<T[]>, which correctly calls delete[] instead of delete to free the memory. Using delete on an array leads to undefined behavior, so this specialization fills a specific, important niche.
2. How does T[] differ from T[3], and why isn't unique_ptr<T[3]> valid?
Let's break down the core differences first:
T[3]is a complete array type: its size (3 elements) is fixed and known at compile time. It represents a fixed-size array of exactly 3Tobjects.T[]is incomplete: it represents an array ofTwith an unspecified size, which is only resolved when the array is dynamically allocated at runtime.
As for why unique_ptr<T[3]> doesn't work: the C++ standard library only provides two primary specializations for unique_ptr:
std::unique_ptr<T>: For managing a single object (usesdelete).std::unique_ptr<T[]>: For managing dynamic arrays (usesdelete[]).
There's no standard specialization for unique_ptr<T[N]> (fixed-size arrays), and here's why:
- Fixed-size arrays allocated on the stack are automatically managed—no smart pointer needed.
- If you allocate a fixed-size array on the heap (e.g.,
new int[3]), it's still a dynamic array at runtime.delete[]doesn't care about the compile-time size, sounique_ptr<int[]>works perfectly well here.
Trying to use unique_ptr<int[3]> will throw a compile error because the compiler can't find a matching template specialization.
3. Are there other uses for T[] as a template type?
Absolutely! Incomplete array types have several handy use cases in generic code and metaprogramming:
- Generic dynamic array handlers: You can write template functions or classes that work with any dynamic array, regardless of its runtime size. For example, a custom array wrapper that accepts
T[]to handle dynamically allocated arrays of any length. - Type trait checks: Utilities like
std::is_arrayrecognizeT[]as an array type, letting you write code that behaves differently for arrays vs. non-arrays. - C++20
std::spancompatibility:std::spancan take aT[]as a constructor argument, allowing it to wrap dynamic arrays without needing compile-time size information. - Template-based array utilities: You can build tools that operate on arrays where the size isn't known until runtime, using
T[]to signal that the array's length is a runtime value.
内容的提问来源于stack exchange,提问作者Costantino Grana

