Cracking C++ (7): Some Containers and Data Structures

lamoon·2025년 8월 24일

Cracking C++

목록 보기
7/8

Def'n: contiguous data structure that holds series of values, all of the same type, each accessed by its position (0-index).

C-Style Arrays

  • Must provide size of the array when declared - and it must be a constant (not variable) or constant expression constexpr
  • in C++, <array> or <vector> is preferred and avoid C-style array

Example 1

int myArray[3];
myArray[0] = 0;
myArray[1] = 0;
myArray[2] = 0;

// also can use following methods to achieve same result as above:
int myArray[3] = { 0 }; // method 1
int myArray[3] = { }; // method 2
int myArray[3] { }; // method 3

Example 2: using initializer lists, where compiler deduces size automatically

int myArray[] { 1, 2, 3, 4 }; // compiler creates array of 4 elemetns

Example 3: partially declaring values, where remaining elements are set to zero

int myArray[3] { 2 }; // index 0 is set to 2. index 1, 2 is set to 0.

Getting size of the array

Example 1 : Older way

size_t arraySize { sizeof(myArray) / sizeof(myArray[0]) };

Example 2: using std::size() method, requires <array>, returns size_t, unsigned integer type in <cstddef>

size_t arraySize { std::size(myArray) };

std::array

  • a fixed-size container - basically a thin wrapper around C-style array. Also can't grow or shrink at run time. (must be known at compile time)
  • better than C-style as it already knows thier own size, are not automatically cast to a pointer to avoid certain type of bugs and have iterators to easily loop over elements
array<int, 3> arr {9, 8, 7};
cout << format("Array size = {}", arr.size()) << endl;
  • C++ also supports CTAD (class template argument deduction), to avoid having to specify template types in <>
array arr {9,8,7}; // also valid

std::vector

  • non-fixed size containers - vector automatically allocates enough memory to hold its element
vector<int> myVector { 11, 22 }; // create a vector of integers

// or you can define it like this using the fact vector supports CTAD
vecotr myVector { 11, 22 };
  • caveat: initializer is required for CTAD to work (i.e. vector myVector don't work)

std::pair

  • group together two values of possibly different types - use first and second public data members. defined in <utility>
pair <double, int> myPair { 1.23, 5 };
cout << format("{} {}", mPair.first, myPair.second);

// also supports CTAD
pair myPair { 1.23, 5 };

std::optional

  • defined in <optional> - holds value of a specific type or nothing
  • can also be used as a return type: removes need to return 'special' values from func'ns like nullptr, end(), -1, EOF, etc. and removes the need to write function as returning boolean, while storing actual result of function in an argument passed to the function as an output parameter
  • class template: have to specify actual type that you need between angle brackets (CTAD not supported) (e.g. optional<int>)
  • reference can't be stored in optional (i.e. optional<T&> don't work - store pointer instead)
optional<int> getData(bool giveIt) {
	if (giveIt) return 42;
    return nullopt; // or return {};
}

// use has_value() to check if optional has a value
cout << "data1.has_value = " << data1.has_value() << endl;

// if it has a value, retrieve via value() or dereferencing operator
cout << "data1.value = " << data1.value() << endl; 
cout << "data1.value = " << *data1 << endl;
  • bad_optional_access may be thrown if empty optional, so we use value_or()
cout << "data2.value = " << data2.value_or(0) << endl;

Structured Bindings

  • allows to declare multiple variables that are initialized with elements from array, struct, pair, etc.
  • unpack multiple values from a tuple-like object to separate variables - number of variables has to match with the expression on the right
array values { 11, 22, 33 };
auto [x, y, z] { values };
  • also work with structs if all non-static members are public
struct Point { double m_x, m_y, m_z; }; 
Point point; 
point.m_x = 1.0; 
point.m_y = 2.0; 
point.m_z = 3.0; 

auto [x, y, z] { point };
  • also possible to create a set of references-to-non-const or references-to-const using structured bindings syntax by using auto& or const auto& instead of auto

0개의 댓글