std::uninitialized_default_construct
出自cppreference.com
| 在標頭 <memory> 定義
|
||
| (1) | (C++17 起) (C++26 起為 constexpr) |
|
| |
(2) | (C++17 起) |
1) 如同用以下方式在未初始化內存區域
[first, last) 上通過默認初始化構造 typename std::iterator_traits<NoThrowForwardIt>::value_type 類型對象:
for (; first != last; ++first)
::new (voidify(*first))
typename std::iterator_traits<NoThrowForwardIt>::value_type;
如果初始化中拋出了異常,那麼以未指定的順序銷毀已構造的對象。
2) 同 (1),但按照
policy 執行。 此重載只有在滿足以下所有條件時才會參與重載決議:
|
|
(C++20 前) |
|
|
(C++20 起) |
參數
| first, last | - | 要初始化的元素範圍的迭代器對 |
| policy | - | 所用的執行策略 |
| 類型要求 | ||
-NoThrowForwardIt 必須滿足老式向前迭代器 (LegacyForwardIterator) 。
| ||
-通過 NoThrowForwardIt 合法實例的自增、複製、比較或間接均不拋出異常。
| ||
複雜度
與 first 與 last 間的距離成線性。
異常
擁有名為 ExecutionPolicy 的模板形參的重載按下列方式報告錯誤:
- 如果作為算法一部分調用的函數的執行拋出異常,且
ExecutionPolicy是標準策略之一,那麼調用 std::terminate。對於任何其他ExecutionPolicy,行為由實現定義。 - 如果算法無法分配內存,那麼拋出 std::bad_alloc。
註解
| 功能特性測試宏 | 值 | 標準 | 功能特性 |
|---|---|---|---|
__cpp_lib_raw_memory_algorithms |
202411L |
(C++26) | constexpr 的特化內存算法, (1)
|
可能的實現
template<class NoThrowForwardIt>
constexpr void uninitialized_default_construct(NoThrowForwardIt first,
NoThrowForwardIt last)
{
using Value = typename std::iterator_traits<NoThrowForwardIt>::value_type;
NoThrowForwardIt current = first;
try
{
for (; current != last; ++current)
{
::new (static_cast<void*>(std::addressof(*current))) Value;
}
}
catch (...)
{
std::destroy(first, current);
throw;
}
}
|
示例
運行此代碼
#include <cstring>
#include <iostream>
#include <memory>
#include <string>
struct S
{
std::string m{"默认值"};
};
int main()
{
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_default_construct(first, last);
for (auto it{first}; it != last; ++it)
std::cout << it->m << '\n';
std::destroy(first, last);
}
catch (...)
{
std::cout << "异常!\n";
}
// 对于标量类型,uninitialized_default_construct
// 通常不会以零填充未初始化的内存区域。
int v[]{1, 2, 3, 4};
const int original[]{1, 2, 3, 4};
std::uninitialized_default_construct(std::begin(v), std::end(v));
// 可能是未定义行为,等待 CWG 1997 得到解决。
// for (const int i : v)
// std::cout << i << ' ';
// 结果未指定。
std::cout <<
(std::memcmp(v, original, sizeof(v)) == 0 ? "未修改\n" : "已修改\n");
}
可能的輸出:
默认值
默认值
默认值
未修改
缺陷報告
下列更改行為的缺陷報告追溯地應用於以前出版的 C++ 標準。
| 缺陷報告 | 應用於 | 出版時的行為 | 正確行為 |
|---|---|---|---|
| LWG 3870 | C++20 | 此算法可能在 const 存儲上創建對象
|
保持禁止 |
參閱
| 在起點和數量所定義的未初始化內存中用默認初始化構造對象 (函數模板) | |
| 在範圍所定義的未初始化內存中用值初始化構造對象 (函數模板) | |
| 在範圍所定義的未初始化內存中用默認初始化構造對象 (算法函數對象) |