C++ Beginner

cpp_016: Comparing C-Style Arrays, std::array, and std::vector in C++

codeaddict 2025. 4. 5. 19:51

1- Introduction

In previous tutorials, we explored different ways to handle collections in C++. We started with traditional C-style arrays, then introduced the dynamic std::vector, and most recently discussed the modern std::array in cpp_015: STL Array in C++ (https://medium.com/@staytechrich/list/cpp-c-beginner-053ab9a0ecc3).

We also examined how these types are passed to functions: C-style arrays as pointers, std::array as objects (by value or reference), and std::vector typically by reference to avoid copying.

Now, it’s time to tie it all together! In this tutorial, we’ll:

  • Summarize the key differences between C-style arrays, std::array, and std::vector.
  • Show examples highlighting these differences.
  • Provide an integrated example using all three in one program.

2- Key Differences with Integrated Examples

2.1 Size

  • C-style array: Fixed, no built-in size method, but size can be calculated with sizeof(arr) / sizeof(arr[0]) in the defining scope.
  • std::array: Fixed, knows its size via .size().
  • std::vector: Dynamic, resizes at runtime.

Example:

#include <iostream>
#include <array>
#include <vector>
using namespace std;

int main() {
    int cstyle[3] = {1, 2, 3};           // Fixed, size calculable in scope
    array<int, 3> stlarr = {4, 5, 6};   // Fixed, has .size()
    vector<int> vec = {7, 8, 9};        // Dynamic

    // Calculate size for C-style array
    int cstyleSize = sizeof(cstyle) / sizeof(cstyle[0]);
    cout << "C-style size: " << cstyleSize << " (calculated with sizeof)\n";
    cout << "std::array size: " << stlarr.size() << endl;
    cout << "std::vector size: " << vec.size() << endl;

    vec.push_back(10); // Vector grows
    cout << "std::vector size after push_back: " << vec.size() << endl;

    return 0;
}

Output:

C-style size: 3 (calculated with sizeof)
std::array size: 3
std::vector size: 3
std::vector size after push_back: 4

2.2 Safety

  • C-style array: No bounds checking.
  • std::array: .at() checks bounds.
  • std::vector: .at() checks bounds.

Example:

#include <iostream>
#include <array>
#include <vector>
using namespace std;

int main() {
    int cstyle[3] = {1, 2, 3};
    array<int, 3> stlarr = {4, 5, 6};
    vector<int> vec = {7, 8, 9};

    cout << "C-style at 5: " << cstyle[5] << endl; // Undefined behavior

    try {
        cout << "std::array at 5: " << stlarr.at(5) << endl;
    } catch (const out_of_range& e) {
        cout << "std::array error: " << e.what() << endl;
    }

    try {
        cout << "std::vector at 5: " << vec.at(5) << endl;
    } catch (const out_of_range& e) {
        cout << "std::vector error: " << e.what() << endl;
    }

    return 0;
}

Output (varies for C-style, random value or crash):

C-style at 5: 32764
ERROR!
std::array at 5: std::array error: array::at: __n (which is 5) >= _Nm (which is 3)
std::vector at 5: std::vector error: vector::_M_range_check: __n (which is 5) >= this->size() (which is 3)

2.3 Flexibility

  • C-style array: Static, no resizing.
  • std::array: Static, fixed size.
  • std::vector: Dynamic, can grow/shrink.
#include <iostream>
#include <array>
#include <vector>
using namespace std;

int main() {
    int cstyle[3] = {1, 2, 3};         // Cannot resize
    array<int, 3> stlarr = {4, 5, 6}; // Cannot resize
    vector<int> vec = {7, 8, 9};      // Can resize

    // Print initial values
    cout << "C-style: "; for (int i = 0; i < 3; i++) cout << cstyle[i] << " ";
    cout << "\nstd::array: "; for (int i = 0; i < 3; i++) cout << stlarr[i] << " ";
    cout << "\nstd::vector: "; for (int i = 0; i < 3; i++) cout << vec[i] << " ";

    vec.push_back(10); // Only vector can grow
    cout << "\nstd::vector after push_back: ";
    for (int i = 0; i < vec.size(); i++) cout << vec[i] << " ";
    cout << endl;

    return 0;
}

Output:

C-style: 1 2 3 
std::array: 4 5 6 
std::vector: 7 8 9 
std::vector after push_back: 7 8 9 10 

2.4 Performance

  • C-style array: Fastest (no overhead).
  • std::array: Nearly as fast.
  • std::vector: Slightly slower due to dynamic management.

2.5 Function Passing

  • C-style array: Passed as a pointer.
  • std::array: Passed by value or reference.
  • std::vector: Passed by reference.

Example

#include <iostream>
#include <array>
#include <vector>
using namespace std;

int sumCStyle(int arr[], int size) {
    int sum = 0;
    for (int i = 0; i < size; i++) sum += arr[i];
    return sum;
}

int sumSTLArray(const array<int, 3>& arr) {
    int sum = 0;
    for (int i = 0; i < arr.size(); i++) sum += arr[i];
    return sum;
}

int sumVector(const vector<int>& vec) {
    int sum = 0;
    for (int i = 0; i < vec.size(); i++) sum += vec[i];
    return sum;
}

int main() {
    int cstyle[3] = {85, 90, 95};
    array<int, 3> stlarr = {88, 92, 87};
    vector<int> vec = {90, 85, 95};
    vec.push_back(88); // Dynamic growth

    cout << "C-style sum: " << sumCStyle(cstyle, 3) << endl;
    cout << "std::array sum: " << sumSTLArray(stlarr) << endl;
    cout << "std::vector sum: " << sumVector(vec) << endl;

    return 0;
}

Output:

C-style sum: 270
std::array sum: 267
std::vector sum: 358