在WebRTC的源码中有如下函数:
1 2 3 4
| template <typename T> std::unique_ptr<T> WrapUnique(T* ptr) { return std::unique_ptr<T>(ptr); }
|
该函数本身不复杂,重点在于它直接返回了一个std::unique_ptr
,据我所知std::unique_ptr
是不能够直接拷贝构造的,如:
1 2
| std::unique_ptr<std::string> s1(new std::string("123")); std::unique_ptr<std::string> s2 = s1;
|
而且WrapUnique经过单步调试,整个函数的执行过程只有执行了一次std::unique_ptr
构造。按照我的理解,至少要执行1次构造,2次拷贝构造的。那么WrapUnique
为什么可以做到了?
结论是:C++编译器对匿名变量做了优化,编译器发现有变量来接收匿名变量,则直接将匿名变量的初始化过程放到接收该匿名变量的对象身上去,免去了后面的拷贝构造的过程。
如下测试代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
| #include <iostream> using namespace std;
class Apple { public: Apple() { id_ = 0; cout << "Apple()" << endl; }
Apple(int id) { id_ = id; cout << "Apple(" << id_ << ")" << endl; }
Apple(const Apple &a) { id_ = a.id_; cout << "Apple(const Apple &a)" << endl; }
Apple& operator=(const Apple &that) { id_ = that.id_; cout << "Apple& operator=(const Apple &that)" << endl; }
~Apple() { cout << "~Apple()" << endl; } private: int id_; };
Apple WrapApple(int id) { return Apple(id); }
int main() { Apple apple = WrapApple(666);
return 0; }
|
不考虑匿名变量的优化,我们猜测执行过程的输出是:
1 2 3
| Apple(666) Apple(const Apple &a) Apple(const Apple &a)
|
但实际执行结果是:
编译器直接对apple对象进行初始化,省去了2次拷贝构造的过程。
WebRTC中的WrapUnique
函数就是利用这个原理。