欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

C++11 emplace_back和push_back的区别

程序员文章站 2022-03-21 16:27:19
...

push_back

void push_back( const T& value );  
void push_back( T& value ); (C++11 起)

后附给定元素 value 到容器尾。

1) 初始化新元素为 value 的副本。

2) 移动 value 进新元素。

若新的 size() 大于 capacity() ,则所有迭代器和引用(包含尾后迭代器)都被非法化。否则仅尾后迭代器被非法化。

参数

value 要后附的元素值。

为使用重载,T必须满足可复制插入和可移动插入的要求。

返回值

复杂度

常数。

异常

若抛出异常(可能因为 Allocator::allocate() 或元素复制/移动构造函数/赋值),则此函数无效果(强异常保证)。

注意

一些实现在 push_back 导致会超出 max_size 的重分配时亦抛出 std::length_error ,由于这会隐式调用 reserve(size()+1) 的等价者。

示例

#include <vector>
#include <iostream>
#include <iomanip>
 
int main()
{
    std::vector<std::string> numbers;
 
    numbers.push_back("abc");
    std::string s = "def";
    numbers.push_back(std::move(s));
 
    std::cout << "vector holds: ";
    for (auto&& i : numbers) std::cout << std::quoted(i) << ' ';
    std::cout << "\nMoved-from string holds " << std::quoted(s) << '\n';
}

输出: 

 C++11 emplace_back和push_back的区别

emplace_back

template< class... Args >
void emplace_back( Args&&... args );
(C++11起,C++17前)
template< class... Args >
reference emplace_back( Args&&... args );
(C++17起)

添加新元素到容器尾。元素通过 std::allocator_traits::construct 构造,它典型地用布置 new 于容器所提供的位置原位构造元素。参数 args... 以 std::forward<Args>(args)... 转发到构造函数。

所有迭代器,包含尾后迭代器,都被非法化。没有引用被非法化。

参数

args 转发到元素构造函数的参数

返回值

(无) C++17前
被插入元素的引用 C++17起

复杂度

常数

异常

若抛出异常,则此函数无效果(强异常保证)。

示例

下列代码用 emplace_back 后附 President 类型对象到 std::deque 。它演示 emplace_back 如何转发参数到 President 的构造函数,并展示如何用 emplace_back 避免用 push_back 时的额外复制或移动操作。

#include <deque>
#include <string>
#include <iostream>
 
struct President
{
    std::string name;
    std::string country;
    int year;
 
    President(std::string p_name, std::string p_country, int p_year)
        : name(std::move(p_name)), country(std::move(p_country)), year(p_year)
    {
        std::cout << "I am being constructed.\n";
    }
    President(President&& other)
        : name(std::move(other.name)), country(std::move(other.country)), year(other.year)
    {
        std::cout << "I am being moved.\n";
    }
    President& operator=(const President& other) = default;
};
 
int main()
{
    std::deque<President> elections;
    std::cout << "emplace_back:\n";
    elections.emplace_back("Nelson Mandela", "South Africa", 1994);
 
    std::deque<President> reElections;
    std::cout << "\npush_back:\n";
    reElections.push_back(President("Franklin Delano Roosevelt", "the USA", 1936));
 
    std::cout << "\nContents:\n";
    for (President const& president: elections) {
        std::cout << president.name << " was elected president of "
                  << president.country << " in " << president.year << ".\n";
    }
    for (President const& president: reElections) {
        std::cout << president.name << " was re-elected president of "
                  << president.country << " in " << president.year << ".\n";
    }
}

输出: 

C++11 emplace_back和push_back的区别

比较

emplace_back:在容器末尾就地构造元素,push_back则没有这个机制,还有push_back的使用可能会导致额外的复制或移动操作。

参考:

https://zh.cppreference.com/w/cpp/container/deque/emplace_back

相关标签: C/C++