文章目录
- STL vector容器emplace_back和push_back的区别
- C++的三法则和五法则
- 比较`emplace_back`和`push_back`函数
- 总结
- reference
欢迎访问个人网络日志🌹🌹知行空间🌹🌹
STL vector容器emplace_back和push_back的区别
这个问题可以讲是C++
面试问到的比较频繁的问题了,今天复习C++
类的默认生成的函数时,使用例子来说明下这两个函数的区别。
C++的三法则和五法则
在C++11
以前,如果一个类需要析构函数,则一定需要拷贝构造函数和拷贝赋值操作符,譬如类包含指针成员时。这个是三法则。
C++11
后又添加了移动语义支持的移动构造函数和移动赋值操作符。因此扩充后称为五法则。
C++11
及以后,编译器会默认为类生成8个函数,分别是:
- 默认构造函数
- 默认析构函数
- 默认复制构造函数
- 默认赋值运算符重载函数
- 默认移动构造函数
- 默认移动赋值运算符重载函数
- 默认取地址函数
- 默认取地址const函数
比较emplace_back
和push_back
函数
push_back
和emplace_back
都是往vector
容器追加一个元素push_back
是复制或者移动一个对像到vector
中emplace_back
支持直接调用对像的构造函数,避免像push_back
那样的复制和移动。
代码比较:
先定义Object
类和包含vector
成员的MultObjects
:
class Object {public:Object() {std::cout << "Object created.\n";}~Object() {std::cout << "Object deleted.\n";}Object(const Object& obj) {std::cout << "Copy constructor.\n";}Object& operator=(const Object &obj) {std::cout << "Copy Assignment.\n";return *this;}Object(Object &&obj) {std::cout << "Move Constuctor.\n";}Object& operator=(const Object &&obj) {std::cout << "Move Assignment.\n";return *this;}
};struct MultObjects
{using Objs = std::vector<Object>;Objs objects;MultObjects(Objs objs) : objects{std::move(objs)}{}
};
注意,MultObjects
包含一个vector
成员,构造函数接受vector
类型值是通过move
来初始化的,这样可以直接将传入的值转化为右值并赋值给成员变量,避免了对像复制。
常规构造push_back
操作:
int main(void)
{std::vector<Object> objects;Object obj;objects.push_back(obj);MultObjects mult_objects(objects);return 0;
}
以上程序运行的输出结果为:
Object created.
Copy constructor.
Copy constructor.
Object deleted.
Object deleted.
Object deleted.
可以看到对像被创建后复制了两次。
改进1:构造MutlObjects
对像时传入move
转化的值。
int main(void)
{std::vector<Object> objects;Object obj;objects.push_back(obj);MultObjects mult_objects(std::move(objects));return 0;
}
程序编译运行后的输出:
# Object created.
# Copy constructor.
# Object deleted.
# Object deleted.
可见对像创建一次,复制一次,比改进前少复制了一次。
改进2:使用emplace_back
int main(void)
{std::vector<Object> objects;objects.emplace_back();MultObjects mult_objects(std::move(objects));return 0;
}
编译运行后程序的输出:
# Object created.
# Object deleted.
可以看到,使用emplace_back
后,没有复制也没有移动,直接调用了对像的构造函数。
总结
C++
标准库提供了emplace_back
函数,可以直接调用对像的构造函数,避免不必要的复制和移动。
reference
- 1.https://en.cppreference.com/w/cpp/container/vector/emplace_back