服装设计有哪些网站,怎么做一个购物平台网站,网站制作推荐新鸿儒,赣州哪里做网站emplace_back() 详解#xff1a;C 就地构造的效率革命
emplace_back() 是 C11 引入的容器成员函数#xff0c;用于在容器尾部就地构造#xff08;而非拷贝或移动#xff09;元素。这一特性显著提升了复杂对象的插入效率#xff0c;尤其适用于构造代价较高的类型。
一、核…emplace_back() 详解C 就地构造的效率革命
emplace_back() 是 C11 引入的容器成员函数用于在容器尾部就地构造而非拷贝或移动元素。这一特性显著提升了复杂对象的插入效率尤其适用于构造代价较高的类型。
一、核心优势就地构造避免拷贝
传统的 push_back() 需要先构造一个临时对象再将其拷贝或移动到容器中
std::vectorstd::string vec;
vec.push_back(hello); // 步骤1: 构造临时 string 对象// 步骤2: 移动临时对象到 vector 中// 步骤3: 销毁临时对象而 emplace_back() 直接在容器尾部的内存空间中构造对象
vec.emplace_back(hello); // 直接在 vector 内存中构造 string 对象// 无需临时对象无需拷贝/移动二、参数与原理
emplace_back() 的原型为
template class... Args
void emplace_back(Args... args);参数Args... args 是一个可变参数模板接受任意数量和类型的参数原理通过完美转发Perfect Forwarding将参数传递给元素类型的构造函数效果直接在容器管理的内存中构造对象无需临时对象
三、示例对比
1. 基本类型示例
std::vectorint vec;
vec.push_back(42); // 拷贝 int 值
vec.emplace_back(42); // 直接构造 int 值// 两者效率相同因为 int 是 POD 类型2. 复杂对象示例
class ExpensiveObject {
public:ExpensiveObject(int x, double y) : x(x), y(y) {// 复杂且耗时的初始化操作}// 拷贝构造函数代价高ExpensiveObject(const ExpensiveObject other) delete;// 移动构造函数代价高ExpensiveObject(ExpensiveObject other) delete;
};std::vectorExpensiveObject vec;// 错误无法使用 push_back因为需要拷贝或移动
// vec.push_back(ExpensiveObject(1, 2.0));// 正确emplace_back 直接构造对象
vec.emplace_back(1, 2.0); // 直接传递构造参数四、完美转发与参数匹配
emplace_back() 支持直接传递构造所需的参数包括
构造函数参数初始化列表隐式类型转换参数
class Person {
public:Person(std::string name, int age) : name(name), age(age) {}private:std::string name;int age;
};std::vectorPerson people;// 使用 emplace_back 传递构造参数
people.emplace_back(Alice, 30); // 直接构造 Person 对象// 使用 push_back 需要显式构造 Person
people.push_back(Person(Bob, 25)); // 先构造临时对象再移动五、与 push_back() 的关键区别
特性emplace_back()push_back()参数接受构造函数的参数包接受已构造的对象左值或右值构造方式就地构造无需临时对象需要先构造临时对象再拷贝/移动支持不可移动类型支持只要构造函数可用不支持必须可拷贝或可移动隐式类型转换支持直接传递转换所需参数需显式转换或提供转换构造函数
六、注意事项 内存扩容若容器需要重新分配内存emplace_back() 仍需移动所有现有元素 异常安全若构造函数抛出异常容器状态保持不变 返回值emplace_back() 不返回新元素的引用C17 起 emplace() 返回 优先使用场景 插入复杂对象如包含动态资源的类插入需要隐式类型转换的对象插入不可拷贝/不可移动的对象
七、进阶应用初始化列表参数
emplace_back() 可以正确处理初始化列表参数
std::vectorstd::vectorint matrix;// 使用 emplace_back 和初始化列表
matrix.emplace_back({1, 2, 3}); // 直接构造内部 vector// 等价于
matrix.push_back(std::vectorint{1, 2, 3});八、性能测试对比
以下代码对比了 push_back 和 emplace_back 的性能差异
#include chrono
#include vector
#include string
#include iostreamstruct ExpensiveToCopy {std::string largeData;ExpensiveToCopy(const char* data) : largeData(data) {}// 模拟高代价的拷贝构造ExpensiveToCopy(const ExpensiveToCopy other) : largeData(other.largeData) {// 模拟耗时操作for (int i 0; i 1000; i) {}}
};int main() {std::vectorExpensiveToCopy vec;// 测试 push_backauto start std::chrono::high_resolution_clock::now();for (int i 0; i 10000; i) {vec.push_back(a very long string that needs to be copied);}auto end std::chrono::high_resolution_clock::now();std::cout push_back time: std::chrono::duration_caststd::chrono::milliseconds(end - start).count() ms std::endl;// 测试 emplace_backvec.clear();start std::chrono::high_resolution_clock::now();for (int i 0; i 10000; i) {vec.emplace_back(a very long string that needs to be copied);}end std::chrono::high_resolution_clock::now();std::cout emplace_back time: std::chrono::duration_caststd::chrono::milliseconds(end - start).count() ms std::endl;return 0;
}九、总结
emplace_back() 是 C 容器库的重要改进它通过就地构造机制显著提升了插入效率尤其适用于
构造代价高昂的对象需要隐式类型转换的对象不可拷贝/不可移动的对象
在现代 C 编程中建议优先使用 emplace_back() 替代 push_back()除非需要明确的类型检查或兼容性保证。