Namespaces
Variants
Views
Actions

Difference between revisions of "cpp/memory/uninitialized move"

From cppreference.com
< cpp‎ | memory
(LWG3870)
(~)
 
(2 intermediate revisions by 2 users not shown)
Line 2: Line 2:
 
{{cpp/memory/navbar}}
 
{{cpp/memory/navbar}}
 
{{dcl begin}}
 
{{dcl begin}}
{{dcl header | memory}}
+
{{dcl header|memory}}
{{dcl | since=c++17 | num= 1 |1=   
+
{{dcl|since=c++17|num=1|1=   
 
template< class InputIt, class NoThrowForwardIt >
 
template< class InputIt, class NoThrowForwardIt >
 
NoThrowForwardIt uninitialized_move( InputIt first, InputIt last,
 
NoThrowForwardIt uninitialized_move( InputIt first, InputIt last,
 
                                     NoThrowForwardIt d_first );
 
                                     NoThrowForwardIt d_first );
 
}}
 
}}
{{dcl | since=c++17 | num= 2 |1=
+
{{dcl|since=c++17|num=2|1=
 
template< class ExecutionPolicy, class ForwardIt, class NoThrowForwardIt >
 
template< class ExecutionPolicy, class ForwardIt, class NoThrowForwardIt >
 
NoThrowForwardIt uninitialized_move( ExecutionPolicy&& policy,
 
NoThrowForwardIt uninitialized_move( ExecutionPolicy&& policy,
Line 15: Line 15:
 
{{dcl end}}
 
{{dcl end}}
  
@1@ Moves elements from the range {{tt|[first, last)}} to an uninitialized memory area beginning at {{tt|d_first}} as if by  
+
@1@ Moves elements from the range {{range|first|last}} to an uninitialized memory area beginning at {{c|d_first}} as if by<br>
{{source|1=
+
{{c multi|
for (; first != last; ++d_first, (void) ++first)
+
for (; first !{{=}} last; ++d_first, (void) ++first)|
  ::new (static_cast<void*>(std::addressof(*d_first)))
+
    ::new (static_cast<void*>(std::addressof(*d_first)))|
      typename std::iterator_traits<NoThrowForwardIt>::value_type(std::move(*first));
+
        typename std::iterator_traits<NoThrowForwardIt>::value_type(std::move(*first));
 
}}
 
}}
  
@@If an exception is thrown during the initialization, some objects in {{tt|[first, last)}} are left in a valid but unspecified state, and the objects already constructed are destroyed in an unspecified order.
+
@@ If an exception is thrown during the initialization, some objects in {{range|first|last}} are left in a valid but unspecified state, and the objects already constructed are destroyed in an unspecified order.
 +
{{rrev|since=c++20|
 +
If {{counted range|d_first|std::distance(first, last)}} overlaps with {{range|first|last}}, the behavior is undefined.
 +
}}
  
@2@ Same as {{v|1}}, but executed according to {{tt|policy}}. {{cpp/algorithm/parallel overload precondition}}
+
@2@ Same as {{v|1}}, but executed according to {{c|policy}}. {{cpp/algorithm/parallel overload precondition}}
  
 
===Parameters===
 
===Parameters===
 
{{par begin}}
 
{{par begin}}
{{par | first, last | the range of the elements to move}}
+
{{par|first, last|the range of the elements to move}}
{{par | d_first | the beginning of the destination range}}
+
{{par|d_first|the beginning of the destination range}}
 
{{par exec pol}}
 
{{par exec pol}}
 
{{par hreq}}
 
{{par hreq}}
{{par req named | InputIt | InputIterator}}
+
{{par req named|InputIt|InputIterator}}
{{par req named | ForwardIt | ForwardIterator}}
+
{{par req named|ForwardIt|ForwardIterator}}
{{par req named | NoThrowForwardIt | ForwardIterator}}
+
{{par req named|NoThrowForwardIt|ForwardIterator}}
{{par req | No increment, assignment, comparison, or indirection through valid instances of {{tt|NoThrowForwardIt}} may throw exceptions.}}
+
{{par req|No increment, assignment, comparison, or indirection through valid instances of {{tt|NoThrowForwardIt}} may throw exceptions.}}
 
{{par end}}
 
{{par end}}
  
Line 42: Line 45:
  
 
===Complexity===
 
===Complexity===
Linear in the distance between {{tt|first}} and {{tt|last}}.
+
Linear in the distance between {{c|first}} and {{c|last}}.
  
 
===Exceptions===
 
===Exceptions===
{{cpp/algorithm/parallel_exceptions_reporting_behavior|singular=yes}}
+
{{cpp/algorithm/parallel exceptions reporting behavior|singular=yes}}
  
 
===Possible implementation===
 
===Possible implementation===
{{eq fun | 1=
+
{{eq fun|1=
 
template<class InputIt, class NoThrowForwardIt>
 
template<class InputIt, class NoThrowForwardIt>
 
NoThrowForwardIt uninitialized_move(InputIt first, InputIt last, NoThrowForwardIt d_first)
 
NoThrowForwardIt uninitialized_move(InputIt first, InputIt last, NoThrowForwardIt d_first)
Line 54: Line 57:
 
     using Value = typename std::iterator_traits<NoThrowForwardIt>::value_type;
 
     using Value = typename std::iterator_traits<NoThrowForwardIt>::value_type;
 
     NoThrowForwardIt current = d_first;
 
     NoThrowForwardIt current = d_first;
     try {
+
     try
         for (; first != last; ++first, (void) ++current) {
+
    {
 +
         for (; first != last; ++first, (void) ++current)
 
             ::new (static_cast<void*>(std::addressof(*current))) Value(std::move(*first));
 
             ::new (static_cast<void*>(std::addressof(*current))) Value(std::move(*first));
        }
 
 
         return current;
 
         return current;
     } catch (...) {
+
     }
 +
    catch (...)
 +
    {
 
         std::destroy(d_first, current);
 
         std::destroy(d_first, current);
 
         throw;
 
         throw;
Line 74: Line 79:
 
#include <string>
 
#include <string>
  
void print(auto rem, auto first, auto last) {
+
void print(auto rem, auto first, auto last)
 +
{
 
     for (std::cout << rem; first != last; ++first)
 
     for (std::cout << rem; first != last; ++first)
 
         std::cout << std::quoted(*first) << ' ';
 
         std::cout << std::quoted(*first) << ' ';
Line 80: Line 86:
 
}
 
}
  
int main() {
+
int main()
     std::string in[] { "Home", "Work!" };
+
{
 +
     std::string in[]{"Home", "Work!"};
 
     print("initially, in: ", std::begin(in), std::end(in));
 
     print("initially, in: ", std::begin(in), std::end(in));
 
+
   
 
     if (
 
     if (
 
         constexpr auto sz = std::size(in);
 
         constexpr auto sz = std::size(in);
         void* out = std::aligned_alloc(alignof(std::string), sizeof(std::string) * sz)
+
         void* out = std::aligned_alloc(alignof(std::string), sizeof(std::string) * sz))
     ) {
+
     {
         try {
+
         try
             auto first {static_cast<std::string*>(out)};
+
        {
             auto last {first + sz};
+
             auto first{static_cast<std::string*>(out)};
 +
             auto last{first + sz};
 
             std::uninitialized_move(std::begin(in), std::end(in), first);
 
             std::uninitialized_move(std::begin(in), std::end(in), first);
 
+
           
 
             print("after move, in: ", std::begin(in), std::end(in));
 
             print("after move, in: ", std::begin(in), std::end(in));
 
             print("after move, out: ", first, last);
 
             print("after move, out: ", first, last);
 
+
           
 
             std::destroy(first, last);
 
             std::destroy(first, last);
 
         }
 
         }
         catch (...) {
+
         catch (...)
 +
        {
 
             std::cout << "Exception!\n";
 
             std::cout << "Exception!\n";
 
         }
 
         }
Line 104: Line 113:
 
     }
 
     }
 
}
 
}
| p=true <!-- move results are indeterminate -->
+
|p=true <!-- move results are indeterminate -->
| output=
+
|output=
 
initially, in: "Home" "Work!"
 
initially, in: "Home" "Work!"
 
after move, in: "" ""
 
after move, in: "" ""
Line 113: Line 122:
 
===Defect reports===
 
===Defect reports===
 
{{dr list begin}}
 
{{dr list begin}}
{{dr list item|wg=lwg|dr=3870|std=C++20|before=this algorithm might create objects on a {{c|const}} storage|after=kept disallowed}}
+
{{dr list item|wg=lwg|dr=3870|std=C++20|before=this algorithm might create objects on a {{c/core|const}} storage|after=kept disallowed}}
 
{{dr list end}}
 
{{dr list end}}
  
 
===See also===
 
===See also===
 
{{dsc begin}}
 
{{dsc begin}}
{{dsc inc | cpp/memory/dsc uninitialized_copy}}
+
{{dsc inc|cpp/memory/dsc uninitialized_copy}}
{{dsc inc | cpp/memory/dsc uninitialized_move_n}}
+
{{dsc inc|cpp/memory/dsc uninitialized_move_n}}
{{dsc inc | cpp/memory/ranges/dsc uninitialized_move}}
+
{{dsc inc|cpp/memory/ranges/dsc uninitialized_move}}
 
{{dsc end}}
 
{{dsc end}}
  
 
{{langlinks|es|ja|ru|zh}}
 
{{langlinks|es|ja|ru|zh}}

Latest revision as of 19:02, 25 July 2023

 
 
Utilities library
General utilities
Relational operators (deprecated in C++20)
 
Dynamic memory management
Uninitialized memory algorithms
Constrained uninitialized memory algorithms
Allocators
Garbage collection support
(C++11)(until C++23)
(C++11)(until C++23)
(C++11)(until C++23)
(C++11)(until C++23)
(C++11)(until C++23)
(C++11)(until C++23)



 
Defined in header <memory>
template< class InputIt, class NoThrowForwardIt >

NoThrowForwardIt uninitialized_move( InputIt first, InputIt last,

                                     NoThrowForwardIt d_first );
(1) (since C++17)
template< class ExecutionPolicy, class ForwardIt, class NoThrowForwardIt >

NoThrowForwardIt uninitialized_move( ExecutionPolicy&& policy,
                                     ForwardIt first, ForwardIt last,

                                     NoThrowForwardIt d_first );
(2) (since C++17)
1) Moves elements from the range [firstlast) to an uninitialized memory area beginning at d_first as if by
for (; first != last; ++d_first, (void) ++first)
    ::new (static_cast<void*>(std::addressof(*d_first)))
        typename std::iterator_traits<NoThrowForwardIt>::value_type(std::move(*first));
If an exception is thrown during the initialization, some objects in [firstlast) are left in a valid but unspecified state, and the objects already constructed are destroyed in an unspecified order.

If d_first + [0std::distance(first, last)) overlaps with [firstlast), the behavior is undefined.

(since C++20)
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)

std::is_execution_policy_v<std::remove_cvref_t<ExecutionPolicy>> is true.

(since C++20)

Contents

[edit] Parameters

first, last - the range of the elements to move
d_first - the beginning of the destination range
policy - the execution policy to use. See execution policy for details.
Type requirements
-
InputIt must meet the requirements of LegacyInputIterator.
-
ForwardIt must meet the requirements of LegacyForwardIterator.
-
NoThrowForwardIt must meet the requirements of LegacyForwardIterator.
-
No increment, assignment, comparison, or indirection through valid instances of NoThrowForwardIt may throw exceptions.

[edit] Return value

Iterator to the element past the last element moved.

[edit] Complexity

Linear in the distance between first and last.

[edit] 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.

[edit] Possible implementation

template<class InputIt, class NoThrowForwardIt>
NoThrowForwardIt uninitialized_move(InputIt first, InputIt last, NoThrowForwardIt d_first)
{
    using Value = typename std::iterator_traits<NoThrowForwardIt>::value_type;
    NoThrowForwardIt current = d_first;
    try
    {
        for (; first != last; ++first, (void) ++current)
            ::new (static_cast<void*>(std::addressof(*current))) Value(std::move(*first));
        return current;
    }
    catch (...)
    {
        std::destroy(d_first, current);
        throw;
    }
}

[edit] Example

#include <cstdlib>
#include <iomanip>
#include <iostream>
#include <memory>
#include <string>
 
void print(auto rem, auto first, auto last)
{
    for (std::cout << rem; first != last; ++first)
        std::cout << std::quoted(*first) << ' ';
    std::cout << '\n';
}
 
int main()
{
    std::string in[]{"Home", "Work!"};
    print("initially, in: ", std::begin(in), std::end(in));
 
    if (
        constexpr auto sz = std::size(in);
        void* out = std::aligned_alloc(alignof(std::string), sizeof(std::string) * sz))
    {
        try
        {
            auto first{static_cast<std::string*>(out)};
            auto last{first + sz};
            std::uninitialized_move(std::begin(in), std::end(in), first);
 
            print("after move, in: ", std::begin(in), std::end(in));
            print("after move, out: ", first, last);
 
            std::destroy(first, last);
        }
        catch (...)
        {
            std::cout << "Exception!\n";
        }
        std::free(out);
    }
}

Possible output:

initially, in: "Home" "Work!"
after move, in: "" ""
after move, out: "Home" "Work!"

[edit] Defect reports

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

DR Applied to Behavior as published Correct behavior
LWG 3870 C++20 this algorithm might create objects on a const storage kept disallowed

[edit] See also

copies a range of objects to an uninitialized area of memory
(function template) [edit]
moves a number of objects to an uninitialized area of memory
(function template) [edit]
moves a range of objects to an uninitialized area of memory
(niebloid)[edit]