C++11新特性 变参模板、完美转发(简述)

变参模板 (Variadic Template)- 使得 emplace 可以接受任意参数,这样就可以适用于任意对象的构建

完美转发 - 使得接收下来的参数 能够原样的传递给对象的构造函数,这带来另一个方便性

先来看看下边的代码,看一下C11标准中提供的变参模板的用法之一:

1 #include <iostream>
 2 #include <vector>
 3 
 4 using namespace std;
 5 
 6 class student
 7 {
 8 public:
 9     student(int age, const char name[64])
10     {
11         this -> age = age;
12         strncpy_s(this->name, sizeof(this->name) - 1, name, sizeof(name));
13         cout << "调用有参构造函数" << endl;
14     }
15 
16     student(const student& stud)
17     {
18         this->age = stud.age;
19         strncpy_s(this->name, sizeof(this->name) - 1, stud.name, sizeof(stud.name));
20         cout << "调用拷贝构造函数" << endl;
21     }
22 
23     ~student()
24     {
25         cout << "调用析构函数" << endl;
26     }
27 
28 private:
29     int age;
30     char name[64];
31 
32 };
33 
34 int main()
35 {
36     vector<student> vectStud;
37 
38     //方法一:
39     //student stud(18, "姓名");
40     //vectStud.push_back(stud);41
42     //方法二:
43     vectStud.push_back(student(18, "姓名"));
44 
45     return 0;
46 }

方法一 与 方法二 的打印结果完全相同:

C++11新特性 变参模板、完美转发(简述)

打印中第一行的有参构造函数是第39行代码调用到的,40行代码将这个对象放置到vector容器中时,会创建一个临时对象进行拷贝。这会造成效能的浪费。

为了解决这个问题C++11中加入了 变参模板 & 完美转发,使得 emplace 可以接受任意参数,这样就可以适用于任意对象的构建,如下代码:

1 #include <iostream>
 2 #include <vector>
 3 
 4 using namespace std;
 5 
 6 class student
 7 {
 8 public:
 9     student(int age, const char name[64])
10     {
11         this -> age = age;
12         strncpy_s(this->name, sizeof(this->name) - 1, name, sizeof(name));
13         cout << "调用有参构造函数" << endl;
14     }
15 
16     student(const student& stud)
17     {
18         this->age = stud.age;
19         strncpy_s(this->name, sizeof(this->name) - 1, stud.name, sizeof(stud.name));
20         cout << "调用拷贝构造函数" << endl;
21     }
22 
23     ~student()
24     {
25         cout << "调用析构函数" << endl;
26     }
27 
28 private:
29     int age;
30     char name[64];
31 
32 };
33 
34 int main()
35 {
36     vector<student> vectStud;
37 
38     //方法一:
39     //student stud(18, "姓名");
40     //vectStud.push_back(stud);
41     //方法二:
42     //vectStud.push_back(student(18, "姓名"));
43 
44     //使用 emplace_back
45     vectStud.emplace_back(18, "姓名");
46 
47     return 0;
48 }

从打印结果可以看出,使用了 emplace_back 之后可以省略一个零时对象,并且不用进行拷贝构造函数的操作。

emplace_back也就相当于一个push_back的操作

C++11新特性 变参模板、完美转发(简述)

还有一个 emplace ,是在指定位置插入相关数据,类似于 insert,如下代码:

1 #include <iostream>
 2 #include <vector>
 3 
 4 using namespace std;
 5 
 6 class student
 7 {
 8 public:
 9     student(int age, const char name[64])
10     {
11         this -> age = age;
12         strncpy_s(this->name, sizeof(this->name) - 1, name, sizeof(name));
13         cout << "调用有参构造函数" << endl;
14         cout << "姓名:" << this->name << "  " << "年龄:" << this->age << endl;
15     }
16 
17     student(const student& stud)
18     {
19         this->age = stud.age;
20         strncpy_s(this->name, sizeof(this->name) - 1, stud.name, sizeof(stud.name));
21         cout << "调用拷贝构造函数" << endl;
22     }
23 
24     ~student()
25     {
26         cout << "调用析构函数" << endl;
27     }
28 
29 private:
30     int age;
31     char name[64];
32 };
33 
34 int main()
35 {
36     vector<student> vectStud;
37 
38     //方法一:
39     //student stud(18, "姓名");
40     //vectStud.push_back(stud);
41     //方法二:
42     //vectStud.push_back(student(18, "姓名"));
43 
44     //使用 emplace_back
45     vectStud.emplace_back(18, "张三");
46 
47     //使用 emplace
48     vectStud.emplace(vectStud.begin(), 20, "李四");
49 
50     return 0;
51 }

打印结果:

C++11新特性 变参模板、完美转发(简述)

这里有个有趣的现象,第5行出现了一个拷贝构造函数,并且调用了3次析构函数。

这是因为 vector 的存储方式决定的,因为 vector 的存储空间是由元素的多少进行变化的,而我们在第48行的代码中使用了 begin() ,在首位置插入,导致内存空间发生了变化。编译器需要将第一个张三拷贝至李四的前方,然后析构掉。如果前方在插入一个,将会把后两个元素再进行拷贝和析构,以此类推。

不同的编译器,对于 vector 新插入元素的拷贝和析构的顺序有可能不同,即使是 VS2015 与 VS2019 在拷贝和析构的顺序上也不相同。

========================================================================================================================
原文链接: https://www.cnblogs.com/CooCoChoco/p/12831736.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/196957

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年2月12日 下午7:24
下一篇 2023年2月12日 下午7:25

相关推荐