牛骨文教育服务平台(让学习变的简单)

实战c++中的vector系列--知道emplace_back为何优于push_back吗?

上一篇博客说道vector中放入struct,我们先构造一个struct对象,再push_back。

那段代码中,之所以不能使用emplace_back,就是因为我们定义的struct没有显示的构造函数。

emplace和解? 
放列的意思。

这次我们不把struct当做vector的元素了,我们把一个class当做vector的元素,写下代码:

#include <iostream>
#include <vector>
#include<string>
using namespace std;
class CText {
private:
    string str;
public:
    text(string s) :str(s) {
    }
    void show()const {
        cout << str << endl;
    }

};
int main()
{
    vector<CText > vi;
    vi.emplace_back("hey");
    vi.front().show();
    vi.push_back("girl");//错误
    vi.back().show();
    return 0;
}

其中vi.push_back(“girl”);这条语句错误,VS2015报错为:

error C2664: “void std::vector<text,std::allocator<_Ty>>::push_back(const text &)”: 无法将参数 1 从“const char [5]”转换为“text &&”

但此时我们稍作修改: 
把 vi.push_back(“girl”) 改为 
vi.push_back(CText(“girl”)); 
问题就解决了。。

简而言之,就是empace_back与push_back相比,替我们省去了调用CText进行构造。

emplace_back 
添加一个新元素到结束的容器。该元件是构成在就地,即没有复制或移动操作进行。

inserts a new element at the end of the vector, right after its current last element. This new element is constructed in place using args as the arguments for its constructor.

This effectively increases the container size by one, which causes an automatic reallocation of the allocated storage space if -and only if- the new vector size surpasses the current vector capacity.

The element is constructed in-place by calling allocator_traits::construct with args forwarded.

A similar member function exists, push_back, which either copies or moves an existing object into the container.

写到这里,你应该明白emplace_back如何是也了吧。

最后再来一段代码,涉及到使用右值引用和std::move的:

#include <vector>
#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.
";
    }
    President(President&& other)
        : name(std::move(other.name)), country(std::move(other.country)), year(other.year)
    {
        std::cout << "I am being moved.
";
    }
    President& operator=(const President& other) = default;
};

int main()
{
    std::vector<President> elections;
    std::cout << "emplace_back:
";
    elections.emplace_back("Nelson Mandela", "South Africa", 1994);

    std::vector<President> reElections;
    std::cout << "
push_back:
";
    reElections.push_back(President("Franklin Delano Roosevelt", "the USA", 1936));

    std::cout << "
Contents:
";
    for (President const& president : elections) {
        std::cout << president.name << " was elected president of "
            << president.country << " in " << president.year << ".
";
    }
    for (President const& president : reElections) {
        std::cout << president.name << " was re-elected president of "
            << president.country << " in " << president.year << ".
";
    }
}

//输出:
emplace_back:
I am being constructed.

push_back:
I am being constructed.
I am being moved.

Contents:
Nelson Mandela was elected president of South Africa in 1994.
Franklin Delano Roosevelt was re-elected president of the USA in 1936.