内存操作基础设施实现分析
标准库提供了底层的内存操作函数,用于在未初始化的内存上构造/析构对象。本文基于 GCC 和 LLVM 的源码,分析内存操作基础设施的内部实现。
一、核心概念
1.1 什么是内存操作
内存操作是容器与内存分配器之间的桥梁:
容器操作 → 内存操作 → 分配器
例如 vector::push_back:
1. 分配器分配原始内存
2. 内存操作在原始内存上构造对象
3. 容器管理对象的生命周期
4. 析构时调用内存操作销毁对象1.2 uninitialized_copy 的实现(源码分析)
cpp
// 源码路径:references/impl/gcc/libstdc++-v3/include/bits/stl_uninitialized.h
template<typename _InputIterator, typename _ForwardIterator>
_ForwardIterator
uninitialized_copy(_InputIterator __first, _InputIterator __last,
_ForwardIterator __result) {
typedef typename iterator_traits<_ForwardIterator>::value_type _ValueType;
// 检查是否可以使用 memcpy/memmove
if (__is_trivially_copyable<_ValueType>::value) {
auto __n = std::distance(__first, __last);
std::memmove(&*__result, &*__first, __n * sizeof(_ValueType));
return __result + __n;
}
// 非平凡类型,逐个构造
for (; __first != __last; ++__first, (void)++__result) {
::new (static_cast<void*>(std::addressof(*__result)))
_ValueType(*__first);
}
return __result;
}1.3 uninitialized_fill 的实现(源码分析)
cpp
// 源码路径:references/impl/gcc/libstdc++-v3/include/bits/stl_uninitialized.h
template<typename _ForwardIterator, typename _Tp>
void
uninitialized_fill(_ForwardIterator __first, _ForwardIterator __last,
const _Tp& __x) {
typedef typename iterator_traits<_ForwardIterator>::value_type _ValueType;
if (__is_trivially_copyable<_ValueType>::value) {
auto __n = std::distance(__first, __last);
std::fill_n(__first, __n, __x);
return;
}
for (; __first != __last; ++__first) {
::new (static_cast<void*>(std::addressof(*__first)))
_ValueType(__x);
}
}二、核心数据结构
2.1 uninitialized_copy
cpp
// GCC 的 uninitialized_copy
template<typename _InputIterator, typename _ForwardIterator>
_ForwardIterator
uninitialized_copy(_InputIterator __first, _InputIterator __last,
_ForwardIterator __result) {
typedef typename iterator_traits<_ForwardIterator>::value_type _ValueType;
// 检查是否可以使用 memcpy/memmove
if (__is_trivially_copyable<_ValueType>::value) {
auto __n = std::distance(__first, __last);
std::memmove(&*__result, &*__first, __n * sizeof(_ValueType));
return __result + __n;
}
// 非平凡类型,逐个构造
for (; __first != __last; ++__first, (void)++__result) {
::new (static_cast<void*>(std::addressof(*__result)))
_ValueType(*__first);
}
return __result;
}2.2 uninitialized_fill
cpp
// GCC 的 uninitialized_fill
template<typename _ForwardIterator, typename _Tp>
void
uninitialized_fill(_ForwardIterator __first, _ForwardIterator __last,
const _Tp& __x) {
typedef typename iterator_traits<_ForwardIterator>::value_type _ValueType;
if (__is_trivially_copyable<_ValueType>::value) {
auto __n = std::distance(__first, __last);
std::fill_n(__first, __n, __x);
return;
}
for (; __first != __last; ++__first) {
::new (static_cast<void*>(std::addressof(*__first)))
_ValueType(__x);
}
}三、GCC vs LLVM 差异对比
┌────────────────────────┬──────────────────────┬──────────────────────┐
│ 特性 │ GCC (libstdc++) │ LLVM (libc++) │
├────────────────────────┼──────────────────────┼──────────────────────┤
│ uninitialized_copy │ 完整 │ 完整 │
│ uninitialized_fill │ 完整 │ 完整 │
│ uninitialized_move │ C++17 │ C++17 │
│ construct_at │ C++20 │ C++20 │
│ destroy_at │ C++17 │ C++17 │
│ trivially_copyable 优化│ 支持 │ 支持 │
│ constexpr 支持 │ C++20 │ C++20 │
└────────────────────────┴──────────────────────┴──────────────────────┘四、最佳实践
内存操作使用指南:
1. 优先使用 construct_at/destroy_at:
· C++20 标准接口
· 更安全
2. 使用 uninitialized_* 操作:
· 在原始内存上构造对象
· 适合自定义分配器
3. 注意异常安全:
· 构造失败时销毁已构造的对象
· 使用 RAII 管理生命周期
4. 优化平凡类型:
· 使用 memcpy/memmove 替代逐个构造
· 编译器会自动优化延伸阅读
- std::vector 实现 — vector 的内存管理
- 分配器模型 — allocator 的实现
- std::string 实现 — string 的内存管理