C++传递对象数组:std::array与普通数组的效率差异对比
Great question! Let’s cut through the noise here—when it comes to passing arrays of objects efficiently, the difference between std::array and plain C-style arrays is usually zero, or so negligible you’ll never notice it—but the why behind that is important to get right.
First, let’s clarify how each gets passed
- Plain C-style arrays: When you write a function like
void process(MyObject arr[]), the compiler doesn’t actually pass the array itself. It silently decays the array into a pointer to its first element (MyObject* arr). That means you’re just passing a single memory address—no copying of the object elements happens here. The catch? You lose compile-time knowledge of the array’s size, so you usually have to pass a separatesize_tparameter to track it. - std::array: If you pass a
std::array<MyObject, N>by value, yes, you’ll copy the entire array (all N objects) which is inefficient. But no one does that on purpose! The standard, efficient way to pass it is by reference:void process(const std::array<MyObject, N>& arr)(or non-const if you need to modify it). This also just passes a reference (under the hood, a pointer-like value) to the original array—no element copies, same as the plain array’s pointer decay.
The efficiency bottom line
When used correctly (pointer + size for plain arrays, reference for std::array), both approaches generate almost identical assembly code after compiler optimizations. Accessing elements (arr[i]) is a direct memory access in both cases—no extra overhead, no hidden function calls, just raw pointer arithmetic under the hood.
The real difference isn’t efficiency—it’s safety and usability
Where std::array shines is in avoiding the pitfalls of plain arrays:
- It retains compile-time size information (via
arr.size(), no need for a separate parameter). - It doesn’t decay to a pointer accidentally, so you can’t accidentally treat it like a single pointer (no off-by-one bugs from forgetting the size).
- It works seamlessly with STL algorithms (like
std::sort,std::for_each) and range-based for loops, making your code cleaner and less error-prone.
Example code to illustrate
Plain array approach (efficient but error-prone)
#include <iostream> struct MyObject { int data; void do_something() const { std::cout << data << " "; } }; void process_plain(MyObject* arr, size_t size) { for (size_t i = 0; i < size; ++i) { arr[i].do_something(); } } int main() { MyObject plain_arr[5] = {{1}, {2}, {3}, {4}, {5}}; process_plain(plain_arr, 5); // Don’t forget the size! return 0; }
std::array approach (efficient and safe)
#include <iostream> #include <array> struct MyObject { int data; void do_something() const { std::cout << data << " "; } }; void process_std(const std::array<MyObject, 5>& arr) { for (const auto& obj : arr) { // Range-based for, no size needed obj.do_something(); } } int main() { std::array<MyObject, 5> std_arr = {{1}, {2}, {3}, {4}, {5}}; process_std(std_arr); // Just pass the array—size is baked in return 0; }
When might you see a difference?
The only time std::array would be less efficient is if you accidentally pass it by value (instead of reference). In that case, the entire array is copied, which is way slower than passing a pointer. But that’s a usage mistake, not a flaw in std::array itself.
内容的提问来源于stack exchange,提问作者dqmis

