Namespaces
Variants
Views
Actions

Difference between revisions of "cpp/memory/uninitialized copy n"

From cppreference.com
< cpp‎ | memory
(+ exception handling)
(Added LWG issue #2133 DR (part 2/2).)
 
(27 intermediate revisions by 9 users not shown)
Line 1: Line 1:
 
{{cpp/title|uninitialized_copy_n}}
 
{{cpp/title|uninitialized_copy_n}}
 
{{cpp/memory/navbar}}
 
{{cpp/memory/navbar}}
{{ddcl | header=memory | since=c++11 |
+
{{dcl begin}}
template< class InputIt, class Size, class ForwardIt >
+
{{dcl header|memory}}
ForwardIt uninitialized_copy_n( InputIt first, Size count, ForwardIt d_first);
+
{{dcl|since=c++11|num=1|1=
 
+
template< class InputIt, class Size, class NoThrowForwardIt >
 +
NoThrowForwardIt uninitialized_copy_n( InputIt first, Size count,
 +
                                      NoThrowForwardIt d_first );
 
}}
 
}}
 +
{{dcl|since=c++17|num=2|1=
 +
template< class ExecutionPolicy, class ForwardIt,
 +
          class Size, class NoThrowForwardIt >
 +
NoThrowForwardIt uninitialized_copy_n( ExecutionPolicy&& policy,
 +
                                      ForwardIt first, Size count,
 +
                                      NoThrowForwardIt d_first );}}
 +
{{dcl end}}
 
                                      
 
                                      
Copies {{tt|count}} elements from a range beginning at {{tt|first}} to an uninitialized memory area beginning at {{tt|d_first}}.
+
@1@ Copies {{c|count}} elements from a range beginning at {{c|first}} to an uninitialized memory area beginning at {{c|d_first}} as if by<br>
 +
{{c multi|
 +
for (; n > 0; ++d_first, (void) ++first, --n)|
 +
    ::new (static_cast<void*>(std::addressof(*d_first)))|
 +
        typename std::iterator_traits<NoThrowForwardIt>::value_type(*first);
 +
}}
 +
 
 +
@@ If an exception is thrown during the initialization, the objects already constructed are destroyed in an unspecified order.
 +
{{rrev|since=c++20|
 +
If {{counted range|d_first|n}} overlaps with {{counted range|first|n}}, the behavior is undefined.
 +
}}
  
If an exception is thrown during the initialization, the function has no effects.  
+
@2@ Same as {{v|1}}, but executed according to {{c|policy}}. {{cpp/algorithm/parallel overload precondition}}
  
 
===Parameters===
 
===Parameters===
 
{{par begin}}
 
{{par begin}}
{{par | first | the beginning of the range of the elements to copy}}
+
{{par|first|the beginning of the range of the elements to copy}}
{{par | d_first | the beginning of the destination range}}
+
{{par|count|the number of elements to copy}}
 +
{{par|d_first|the beginning of the destination range}}
 +
{{par exec pol}}
 
{{par hreq}}
 
{{par hreq}}
{{par req concept | InputIt | InputIterator}}
+
{{par req named|InputIt|InputIterator}}
{{par req concept | ForwardIt | ForwardIterator}}
+
{{par req named|ForwardIt|ForwardIterator}}
 +
{{par req named|NoThrowForwardIt|ForwardIterator}}
 +
{{par req|No increment, assignment, comparison, or indirection through valid instances of {{tt|NoThrowForwardIt}} may throw exceptions.}}
 
{{par end}}
 
{{par end}}
  
Line 24: Line 47:
  
 
===Complexity===
 
===Complexity===
Linear in {{tt|count}}.
+
Linear in {{c|count}}.
 +
 
 +
===Exceptions===
 +
{{cpp/algorithm/parallel_exceptions_reporting_behavior|singular=yes}}
  
 
===Possible implementation===
 
===Possible implementation===
{{eq fun | 1=
+
{{eq fun|1=
template<class InputIt, class Size, class ForwardIt>
+
template<class InputIt, class Size, class NoThrowForwardIt>
ForwardIt uninitialized_copy_n(InputIt first, Size count, ForwardIt d_first)
+
NoThrowForwardIt uninitialized_copy_n(InputIt first, Size count, NoThrowForwardIt d_first)
 
{
 
{
     typedef typename std::iterator_traits<ForwardIt>::value_type Value;
+
     using T = typename std::iterator_traits<NoThrowForwardIt>::value_type;
     ForwardIt current = d_first;
+
     NoThrowForwardIt current = d_first;
     try {
+
     try
         for (; count > 0; ++first, ++current, --count) {
+
    {
             ::new (static_cast<void*>(&*current)) Value(*first);
+
         for (; count > 0; ++first, (void) ++current, --count)
        }
+
             ::new (static_cast<void*>(std::addressof(*current))) T(*first);
     } catch (...) {
+
    }
         for (; d_first != current; ++d_first) {
+
     catch (...)
             d_first->~Value();
+
    {
        }
+
         for (; d_first != current; ++d_first)
 +
             d_first->~T();
 
         throw;
 
         throw;
 
     }
 
     }
Line 49: Line 76:
 
===Example===
 
===Example===
 
{{example
 
{{example
| code=
+
|code=
 
#include <algorithm>
 
#include <algorithm>
 
#include <iostream>
 
#include <iostream>
Line 60: Line 87:
 
{
 
{
 
     std::vector<std::string> v = {"This", "is", "an", "example"};
 
     std::vector<std::string> v = {"This", "is", "an", "example"};
 
+
   
 
     std::string* p;
 
     std::string* p;
 
     std::size_t sz;
 
     std::size_t sz;
     std::tie(p, sz) = std::get_temporary_buffer<std::string>(v.size());
+
     std::tie(p, sz) = std::get_temporary_buffer<std::string>(v.size());
 
     sz = std::min(sz, v.size());
 
     sz = std::min(sz, v.size());
 
+
   
 
     std::uninitialized_copy_n(v.begin(), sz, p);
 
     std::uninitialized_copy_n(v.begin(), sz, p);
 
+
   
     for (std::string* i = p; i != p+sz; ++i) {
+
     for (std::string* i = p; i != p + sz; ++i)
 +
    {
 
         std::cout << *i << ' ';
 
         std::cout << *i << ' ';
 
         i->~basic_string<char>();
 
         i->~basic_string<char>();
 
     }
 
     }
 +
    std::cout << '\n';
 +
   
 
     std::return_temporary_buffer(p);
 
     std::return_temporary_buffer(p);
 
}
 
}
| output=
+
|p=true
 +
|output=
 
This is an example
 
This is an example
 
}}
 
}}
 +
 +
===Defect reports===
 +
{{dr list begin}}
 +
{{dr list item|wg=lwg|dr=2133|std=C++98|before=the effect description used a {{c/core|for}} loop with the iteration<br>expression {{c|++d_first, ++first, --n}}, which results<br>in argument-dependent lookups of {{c/core|operator,}}|after=discards the value<br>of one operand to<br>disable those ADLs}}
 +
{{dr list item|wg=lwg|dr=2433|std=C++11|before=this algorithm might be hijacked by overloaded {{c/core|operator&}}|after=uses {{lc|std::addressof}}}}
 +
{{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}}
  
 
===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/ranges/dsc uninitialized_copy_n}}
 
{{dsc end}}
 
{{dsc end}}
  
[[de:cpp/memory/uninitialized copy n]]
+
{{langlinks|de|es|fr|it|ja|pt|ru|zh}}
[[es:cpp/memory/uninitialized copy n]]
+
[[fr:cpp/memory/uninitialized copy n]]
+
[[it:cpp/memory/uninitialized copy n]]
+
[[ja:cpp/memory/uninitialized copy n]]
+
[[pt:cpp/memory/uninitialized copy n]]
+
[[ru:cpp/memory/uninitialized copy n]]
+
[[zh:cpp/memory/uninitialized copy n]]
+

Latest revision as of 21:58, 4 March 2024

 
 
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 Size, class NoThrowForwardIt >

NoThrowForwardIt uninitialized_copy_n( InputIt first, Size count,

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

          class Size, class NoThrowForwardIt >
NoThrowForwardIt uninitialized_copy_n( ExecutionPolicy&& policy,
                                       ForwardIt first, Size count,

                                       NoThrowForwardIt d_first );
(2) (since C++17)
1) Copies count elements from a range beginning at first to an uninitialized memory area beginning at d_first as if by
for (; n > 0; ++d_first, (void) ++first, --n)
     ::new (static_cast<void*>(std::addressof(*d_first)))
        typename std::iterator_traits<NoThrowForwardIt>::value_type(*first);
If an exception is thrown during the initialization, the objects already constructed are destroyed in an unspecified order.

If d_first + [0n) overlaps with first + [0n), 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 - the beginning of the range of the elements to copy
count - the number of elements to copy
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 copied.

[edit] Complexity

Linear in count.

[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 Size, class NoThrowForwardIt>
NoThrowForwardIt uninitialized_copy_n(InputIt first, Size count, NoThrowForwardIt d_first)
{
    using T = typename std::iterator_traits<NoThrowForwardIt>::value_type;
    NoThrowForwardIt current = d_first;
    try
    {
        for (; count > 0; ++first, (void) ++current, --count)
            ::new (static_cast<void*>(std::addressof(*current))) T(*first);
    }
    catch (...)
    {
        for (; d_first != current; ++d_first)
            d_first->~T();
        throw;
    }
    return current;
}

[edit] Example

#include <algorithm>
#include <iostream>
#include <memory>
#include <string>
#include <tuple>
#include <vector>
 
int main()
{
    std::vector<std::string> v = {"This", "is", "an", "example"};
 
    std::string* p;
    std::size_t sz;
    std::tie(p, sz) = std::get_temporary_buffer<std::string>(v.size());
    sz = std::min(sz, v.size());
 
    std::uninitialized_copy_n(v.begin(), sz, p);
 
    for (std::string* i = p; i != p + sz; ++i)
    {
        std::cout << *i << ' ';
        i->~basic_string<char>();
    }
    std::cout << '\n';
 
    std::return_temporary_buffer(p);
}

Possible output:

This is an example

[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 2133 C++98 the effect description used a for loop with the iteration
expression ++d_first, ++first, --n, which results
in argument-dependent lookups of operator,
discards the value
of one operand to
disable those ADLs
LWG 2433 C++11 this algorithm might be hijacked by overloaded operator& uses std::addressof
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]
copies a number of objects to an uninitialized area of memory
(niebloid)[edit]