std::uninit...e_construct(3)

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

πŸŽ€ std::uninit...e_construct(3) πŸŽ€

okay so bestie, welcome to the C++ Standard Libary page for std::uninit...e_construct(3) β€” yes, the title is literally truncated like that in the header, and the actual function we're hyping up is std::uninitialized_value_construct. no cap, we're doing uninitialized memory together. πŸ’–

✨ NAME ✨

std::uninitialized_value_construct - std::uninitialized_value_construct

like... it's the same name on both sides of the dash. iconic behavior, honestly. πŸ’…

πŸ“œ Synopsis πŸ“œ

Defined in header <memory>

template< class ForwardIt >
void uninitialized_value_construct( ForwardIt first, ForwardIt last );
(1) (since C++17)

template< class ExecutionPolicy, class ForwardIt >
void uninitialized_value_construct( ExecutionPolicy&& policy,
                                    ForwardIt first, ForwardIt last );
(2) (since C++17)

(1) Constructs objects of type typename iterator_traits<ForwardIt>::value_type in the uninitialized storage designated by the range [first, last) by value-initialization, as if by:

for (; first != last; ++first)
    ::new (static_cast<void*>(std::addressof(*first)))
        typename std::iterator_traits<ForwardIt>::value_type();

If an exception is thrown during the initialization, the objects already constructed are destroyed in an unspecified order. 😭

(2) Same as (1), but executed according to policy. This overload participates in overload resolution only if std::is_execution_policy_v<std::decay_t<ExecutionPolicy>> is true (until C++20), or if std::is_execution_policy_v<std::remove_cvref_t<ExecutionPolicy>> is true (since C++20).

🧸 Parameters 🧸

  • first, last β€” the range of the elements to initialize. that's the whole little memory zone, bestie.
  • policy β€” the execution policy to use. See execution policy for details. πŸ‘€

🌟 Type requirements 🌟

  • ForwardIt must meet the requirements of LegacyForwardIterator.
  • No increment, assignment, comparison, or indirection through valid instances of ForwardIt may throw exceptions.

🫢 Return value 🫢

(none)

literally nothing comes back, and that's the vibe. 🫢

🌈 Complexity 🌈

Linear in the distance between first and last.

πŸ’€ Exceptions πŸ’€

The overload with a template parameter named ExecutionPolicy reports errors as follows:

  • If execution of a function invoked as part of the algorithm throws an exception and ExecutionPolicy is one of the standard policies, std::terminate is called. For any other ExecutionPolicy, the behavior is implementation-defined.
  • If the algorithm fails to allocate memory, std::bad_alloc is thrown.

🧚 Possible implementation 🧚

template<class ForwardIt>
void uninitialized_value_construct(ForwardIt first, ForwardIt last)
{
    using Value = typename std::iterator_traits<ForwardIt>::value_type;
    ForwardIt current = first;
    try
    {
        for (; current != last; ++current)
            ::new (const_cast<void*>(static_cast<const volatile void*>(
                std::addressof(*current)))) Value();
    }
    catch (...)
    {
        std::destroy(first, current);
        throw;
    }
}

πŸ“ Example πŸ“

cppreference slaps the little // Run this code label on it, and here's the code:

#include <iostream>
#include <memory>
#include <string>

int main()
{
    struct S { std::string m{"Default value"}; };

    constexpr int n{3};
    alignas(alignof(S)) unsigned char mem[n * sizeof(S)];

    try
    {
        auto first{reinterpret_cast<S*>(mem)};
        auto last{first + n};

        std::uninitialized_value_construct(first, last);

        for (auto it{first}; it != last; ++it)
            std::cout << it->m << '\n';

        std::destroy(first, last);
    }
    catch (...)
    {
        std::cout << "Exception!\n";
    }

    // Notice that for "trivial types" the
    // uninitialized_value_construct
    // zero-fills the given uninitialized memory area.
    int v[]{1, 2, 3, 4};
    for (const int i : v)
        std::cout << i << ' ';
    std::cout << '\n';
    std::uninitialized_value_construct(std::begin(v), std::end(v));
    for (const int i : v)
        std::cout << i << ' ';
    std::cout << '\n';
}

⭐ Output ⭐

Default value
Default value
Default value
1 2 3 4
0 0 0 0

🩹 Defect reports 🩹

The following behavior-changing defect reports were applied retroactively to previously published C++ standards.

  • LWG 3870 β€” applied to C++20. Behavior as published: this algorithm might create objects on a const storage. Correct behavior: kept disallowed.

πŸ‘€ See also πŸ‘€

  • uninitialized_value_construct_n (C++17) β€” constructs objects by value-initialization in an uninitialized area of memory, defined by a start and a count (function template).
  • uninitialized_default_construct (C++17) β€” constructs objects by default-initialization in an uninitialized area of memory, defined by a range (function template).
  • ranges::uninitialized_value_construct (C++20) β€” constructs objects by value-initialization in an uninitialized area of memory, defined by a range (niebloid).

that's the whole page, bestie. source/version + date: http://cppreference.com β€’ 2024.06.10 β€’ page: std::uninit...e_construct(3). mwah πŸ’‹

πŸ“¦ where this page comes from