std::vector::vector(3)

πŸ“¦ version 2024.07.05, in nixpkgs unstable, opensuse-leap 16.0

πŸ‘‘ std::vector::vector(3) β€” C++ Standard Libary

Okay so this is the manual page for std::vector::vector(3) from the C++ Standard Libary, and it’s literally the constructor buffet for std::vector. Bestie, there are eleven overloads here, so grab a snack. πŸ’–


🌸 NAME

std::vector::vector β€” yes, it’s std::vector::vector. The name ate and left no crumbs. πŸ’…


✨ Synopsis

vector();
vector() noexcept(noexcept(Allocator()));
explicit vector( const Allocator& alloc );
explicit vector( const Allocator& alloc ) noexcept;
explicit vector( size_type count,
                 const T& value = T(),
                 const Allocator& alloc = Allocator() );
vector( size_type count,
        const T& value,
        const Allocator& alloc = Allocator() );
explicit vector( size_type count );
explicit vector( size_type count,
                 const Allocator& alloc = Allocator() );
template< class InputIt >
vector( InputIt first, InputIt last,
        const Allocator& alloc = Allocator() );
vector( const vector& other );
vector( const vector& other,
        const Allocator& alloc );
vector( vector&& other );
vector( vector&& other, const Allocator& alloc );
vector( std::initializer_list<T> init,
        const Allocator& alloc = Allocator() );
template< container-compatible-range<T> R >
constexpr vector( std::from_range_t, R&& rg,
                  const Allocator& alloc = Allocator() );

Constructs a new container from a variety of data sources, optionally using a user supplied allocator alloc. It’s giving β€œchoose your own adventure” but for vector construction. πŸ¦‹

πŸ’« The overloads, one by one (1)–(11)

  • (1) β€” vector(); until C++17. Since C++17 it’s vector() noexcept(noexcept(Allocator()));; constexpr since C++20. Default constructor: constructs an empty container with a default-constructed allocator.
  • (2) β€” explicit vector( const Allocator& alloc ); until C++17. Since C++17 it’s explicit vector( const Allocator& alloc ) noexcept;; constexpr since C++20. Constructs an empty container with the given allocator alloc.
  • (3) β€” until C++11: explicit vector( size_type count, const T& value = T(), const Allocator& alloc = Allocator() );. Since C++11: vector( size_type count, const T& value, const Allocator& alloc = Allocator() );, and constexpr since C++20. Constructs the container with count copies of elements with value value.
  • (4) β€” since C++11, until C++14: explicit vector( size_type count );. Since C++14: explicit vector( size_type count, const Allocator& alloc = Allocator() );, and constexpr since C++20. Constructs the container with count default-inserted instances of T. No copies are made.
  • (5) β€” template< class InputIt > vector( InputIt first, InputIt last, const Allocator& alloc = Allocator() );; constexpr since C++20. Constructs the container with the contents of the range [first, last).
    • Until C++11: this constructor has the same effect as vector(static_cast<size_type>(first), static_cast<value_type>(last), a) if InputIt is an integral type.
    • Since C++11: this overload participates in overload resolution only if InputIt satisfies LegacyInputIterator, to avoid ambiguity with the overload (3).
  • (6) β€” vector( const vector& other );; constexpr since C++20. Copy constructor. Constructs the container with the copy of the contents of other.
    • Since C++11: the allocator is obtained as if by calling std::allocator_traits<allocator_type>::select_on_container_copy_construction(other.get_allocator()).
  • (7) β€” vector( const vector& other, const Allocator& alloc );; since C++11; constexpr since C++20. Constructs the container with the copy of the contents of other, using alloc as the allocator.
    • Since C++23: during class template argument deduction, only the first argument contributes to the deduction of the container’s Allocator template parameter.
  • (8) β€” vector( vector&& other );; since C++11; noexcept since C++17; constexpr since C++20. Move constructor. Constructs the container with the contents of other using move semantics. Allocator is obtained by move-construction from the allocator belonging to other. After the move, other is guaranteed to be empty().
  • (9) β€” vector( vector&& other, const Allocator& alloc );; since C++11; constexpr since C++20. Allocator-extended move constructor. Using alloc as the allocator for the new container, moving the contents from other; if alloc != other.get_allocator(), this results in an element-wise move. (In that case, other is not guaranteed to be empty after the move.)
    • Since C++23: during class template argument deduction, only the first argument contributes to the deduction of the container’s Allocator template parameter.
  • (10) β€” vector( std::initializer_list<T> init, const Allocator& alloc = Allocator() );; since C++11; constexpr since C++20. Constructs the container with the contents of the initializer list init.
  • (11) β€” template< container-compatible-range<T> R > constexpr vector( std::from_range_t, R&& rg, const Allocator& alloc = Allocator() );; since C++23. Constructs the container with the contents of the range rg.

🫢 Parameters

  • alloc β€” allocator to use for all memory allocations of this container
  • count β€” the size of the container
  • value β€” the value to initialize elements of the container with
  • first, last β€” the range [first, last) to copy the elements from
  • other β€” another container to be used as source to initialize the elements of the container with
  • init β€” initializer list to initialize the elements of the container with
  • rg β€” a container compatible range, that is, an input_range whose elements are convertible to T

⚑ Complexity

  • 1, 2) Constant.
  • 3, 4) Linear in count.
  • 5) Given the distance between first and last as N,
    • If first and last are both forward, bidirectional or random-access iterators,
      • The copy constructor of T is only called N times, and
      • No reallocation occurs.
    • Otherwise (first and last are just input iterators),
      • The copy constructor of T is called O(N) times, and
      • Reallocation occurs O(log N) times.
  • 6, 7) Linear in size of other.
  • 8) Constant.
  • 9) Linear if alloc != other.get_allocator(), otherwise constant.
  • 10) Linear in size of init.
  • 11) Given ranges::distance(rg) as N,
    • If R models ranges::forward_range or ranges::sized_range,
      • Initializes exactly N elements from the result of dereferencing successive iterators of rg, and
      • No reallocation occurs.
    • Otherwise (R models input range),
      • The copy or move constructor of T is called O(N) times, and
      • Reallocation occurs O(log N) times.

🚨 Exceptions

Calls to Allocator::allocate may throw. That’s the throw tea here, bestie. 😭


πŸ“ Notes

After container move construction (overload (8)), references, pointers, and iterators (other than the end iterator) to other remain valid, but refer to elements that are now in *this. The current standard makes this guarantee via the blanket statement in [container.reqmts]/67, and a more direct guarantee is under consideration via LWG issue 2321.

The overload (4) zeroes out elements of non-class types such as int, which is different from the behavior of new[], which leaves them uninitialized. To match the behavior of new[], a custom Allocator::construct can be provided which leaves such elements uninitialized.

Note that the presence of list-initializing constructor (10) means list initialization and direct initialization do different things:

std::vector<int> b{3}; // creates a 1-element vector holding {3}
std::vector<int> d(3); // creates a 3-element vector holding {0, 0, 0}

std::vector<int> p{1, 2}; // creates a 2-element vector holding {1, 2}
std::vector<int> q(1, 2); // creates a 1-element vector holding {2}

🌈 Feature-test macro

  • __cpp_lib_containers_ranges β€” 202202L, (C++23), Ranges-aware construction and insertion; overload (11)

🌸 EXAMPLE 🌸

okay bestie, this is the part where we actually run stuff, and honestly? it's giving study date energy. look at this little helper that teaches std::vector how to print itself, because vectors are iconic but they don't come with a << πŸŽ€

// Run this code

#include <iostream>
#include <string>
#include <vector>

template<typename T>
std::ostream& operator<<(std::ostream& s, const std::vector<T>& v)
{
    s.put('{');
    for (char comma[]{'\0', ' ', '\0'}; const auto& e : v)
        s << comma << e, comma[0] = ',';
    return s << "}\n";
}

int main()
{
    // C++11 initializer list syntax:
    std::vector<std::string> words1{"the", "frogurt", "is", "also", "cursed"};
    std::cout << "1: " << words1;

    // words2 == words1
    std::vector<std::string> words2(words1.begin(), words1.end());
    std::cout << "2: " << words2;

    // words3 == words1
    std::vector<std::string> words3(words1);
    std::cout << "3: " << words3;

    // words4 is {"Mo", "Mo", "Mo", "Mo", "Mo"}
    std::vector<std::string> words4(5, "Mo");
    std::cout << "4: " << words4;

    auto const rg = {"cat", "cow", "crow"};
#ifdef __cpp_lib_containers_ranges
    std::vector<std::string> words5(std::from_range, rg); // overload (11)
#else
    std::vector<std::string> words5(rg.begin(), rg.end()); // overload (5)
#endif
    std::cout << "5: " << words5;
}

and the glow-up it produces ✨

1: {the, frogurt, is, also, cursed}
2: {the, frogurt, is, also, cursed}
3: {the, frogurt, is, also, cursed}
4: {Mo, Mo, Mo, Mo, Mo}
5: {cat, cow, crow}

like, five different constructors, five different vibes, all of them slaying πŸ’… (and yes, "frogurt" is canonically cursed, that's not a typo, that's lore 🐸)


πŸ’€ DEFECT REPORTS πŸ’€

so the committee looked back at the older standards and went "oop, we gotta fix that retroactively" β€” these are the behavior-changing defect reports that got applied to previously published C++ standards. no cap, some of these were messy πŸ™ˆ

  • LWG 134 β€” applied to C++98. as published: overload (5) allowed up to 2N constructor calls in the input iterator case. corrected to: O(N) calls.
  • LWG 868 β€” applied to C++98. as published: for overload (4), the elements in the container were default constructed. corrected to: they are value-initialized.
  • LWG 2193 β€” applied to C++11. as published: the default constructor is explicit. corrected to: made non-explicit.
ngl, "up to 2N calls" was giving chaos energy and I'm so glad that got nerfed 😭

πŸ¦‹ SEE ALSO πŸ¦‹

you want more? of course you do, main character behavior 🫢

  • assign β€” assigns values to the container (public member function)
  • operator= β€” assigns values to the container (public member function)

that's the whole page, bestie!! go forth and construct vectors, you're literally an icon now πŸ‘‘βœ¨

sourced from cppreference.com, version dated 2024.06.10, for std::vector::vector(3). mwah πŸ’–
πŸ“¦ where this page comes from