#include <iostream>
#include <vector>
#include <list>
#include <numeric> // For std::iota
#include <algorithm> // For std::generate
// Helper function to print vector elements using standard C++20 range or classic const reference
template <typename T>
void printVector(const char* title, const std::vector<T>& vec) {
std::cout << "--- " << title << " ---\n[ ";
for (std::size_t i = 0; i < vec.size(); ++i) {
std::cout << vec[i] << (i + 1 < vec.size() ? ", " : " ");
}
std::cout << "]\n\n";
}
int main() {
// -------------------------------------------------------------------------
// EXAMPLE 1: Default Construction (Empty Vector)
// Constructs an empty vector with size 0 and capacity 0.
// -------------------------------------------------------------------------
std::vector<int> emptyVec;
printVector("1. Default Construction (Empty Vector)", emptyVec);
// -------------------------------------------------------------------------
// EXAMPLE 2: Size Initialization with Default/Specified Values
// Allocates space for N elements, filled with a default value.
// -------------------------------------------------------------------------
// Creates a vector of 5 elements, all defaulted to 0
std::vector<int> sizeOnlyVec(5);
printVector("2a. Fill with Default Value (5 zeros)", sizeOnlyVec);
// Creates a vector of 5 elements, all set to 42
std::vector<int> filledVec(5, 42);
printVector("2b. Fill with Specified Value (5 forty-twos)", filledVec);
// -------------------------------------------------------------------------
// EXAMPLE 3: Initializer List (C++11)
// Directly populates the vector with a list of values.
// NOTE: Prefer brace initialization `{}` for explicit values.
// -------------------------------------------------------------------------
std::vector<int> listInitVec = {10, 20, 30, 40, 50};
printVector("3. Initializer List Initialization", listInitVec);
// -------------------------------------------------------------------------
// EXAMPLE 4: Copy and Move Construction
// Creates a new vector from an existing vector.
// -------------------------------------------------------------------------
std::vector<int> sourceVec = {1, 2, 3, 4};
// Copy construction (duplicates elements)
std::vector<int> copiedVec(sourceVec);
printVector("4a. Copy Construction", copiedVec);
// Move construction (transfers ownership of dynamic memory)
std::vector<int> movedVec(std::move(sourceVec));
printVector("4b. Move Construction", movedVec);
// -------------------------------------------------------------------------
// EXAMPLE 5: Range-Based Initialization (Iterator Pairs)
// Populates vector from any iterator pair.
// -------------------------------------------------------------------------
int rawArr[] = {100, 200, 300, 400};
std::vector<int> fromCArray(std::begin(rawArr), std::end(rawArr));
printVector("5a. Range Init from C-Style Array", fromCArray);
std::list<int> srcList = {7, 8, 9};
std::vector<int> fromList(srcList.begin(), srcList.end());
printVector("5b. Range Init from std::list", fromList);
// -------------------------------------------------------------------------
// EXAMPLE 6: Pre-Allocated Capacity with Reserve (Performance Best Practice)
// Avoids repeated dynamic reallocations when filling a vector sequentially.
// -------------------------------------------------------------------------
std::vector<int> reservedVec;
reservedVec.reserve(5); // Allocates capacity for 5 elements, size remains 0
for (int i = 1; i <= 5; ++i) {
reservedVec.push_back(i * 10);
}
printVector("6. Reserved Capacity + push_back/emplace_back", reservedVec);
// -------------------------------------------------------------------------
// EXAMPLE 7: Sequence Generation (std::iota)
// Fills vector with sequentially increasing values.
// -------------------------------------------------------------------------
std::vector<int> sequenceVec(5); // Must pre-size the vector first
std::iota(sequenceVec.begin(), sequenceVec.end(), 1); // Generates 1, 2, 3, 4, 5
printVector("7. Sequential Generation (std::iota)", sequenceVec);
// -------------------------------------------------------------------------
// EXAMPLE 8: Generator Function (std::generate)
// Fills vector using a custom lambda function or generator logic.
// -------------------------------------------------------------------------
std::vector<int> generatedVec(5);
int current = 2;
std::generate(generatedVec.begin(), generatedVec.end(), [¤t]() {
int val = current;
current *= 2;
return val;
}); // Generates powers of 2: 2, 4, 8, 16, 32
printVector("8. Generator-Based Initialization (std::generate)", generatedVec);
}
/*
run:
--- 1. Default Construction (Empty Vector) ---
[ ]
--- 2a. Fill with Default Value (5 zeros) ---
[ 0, 0, 0, 0, 0 ]
--- 2b. Fill with Specified Value (5 forty-twos) ---
[ 42, 42, 42, 42, 42 ]
--- 3. Initializer List Initialization ---
[ 10, 20, 30, 40, 50 ]
--- 4a. Copy Construction ---
[ 1, 2, 3, 4 ]
--- 4b. Move Construction ---
[ 1, 2, 3, 4 ]
--- 5a. Range Init from C-Style Array ---
[ 100, 200, 300, 400 ]
--- 5b. Range Init from std::list ---
[ 7, 8, 9 ]
--- 6. Reserved Capacity + push_back/emplace_back ---
[ 10, 20, 30, 40, 50 ]
--- 7. Sequential Generation (std::iota) ---
[ 1, 2, 3, 4, 5 ]
--- 8. Generator-Based Initialization (std::generate) ---
[ 2, 4, 8, 16, 32 ]
*/