移动语义:
传统 C++ 通过拷贝构造函数和赋值操作符为类对象设计了拷贝/复制的概念,但为了实现对资源的移动操作, 调用者必须使用先复制、再析构的方式,否则就需要自己实现移动对象的接口。 试想,搬家的时候是把家里的东西直接搬到新家去,而不是将所有东西复制一份(重买)再放到新家、 再把原来 的东西全部扔掉(销毁),这是非常反人类的一件事情。 传统的 C++ 没有区分『移动』和『拷贝』的概念,造成了大量的数据拷贝,浪费时间和空间。 右值 引用的出现恰好就解决了这两个概念的混淆问题,例如:
移动语义:
~/test/test_10
$ cat test3.cpp
#include <iostream>
using namespace std;
class A {
public:
int *pointer;
A() : pointer(new int(1))
{
std::cout << "构造" << pointer << std::endl;
}
A(const A& a) : pointer(new int(*a.pointer))
{
std::cout << "A(A& a)拷贝" << pointer << std::endl;
}
A(A&& a) : pointer(a.pointer)
{
a.pointer = nullptr;
std::cout << "移动" << pointer << std::endl;
}
~A()
{
std::cout << "析构" << pointer << std::endl;
delete pointer;
}
};
A return_rvalue(bool test)
{
A a,b;
if (test) {
return a;
}
return b;
}
void test_1(void)
{
cout << "++++++++++++=" << __FUNCTION__ << endl;
A obj = return_rvalue(false);
std::cout << "obj:" << std::endl;
std::cout << obj.pointer << std::endl;
std::cout << *obj.pointer << std::endl;
}
int main(int argc, char *const argv[])
{
test_1();
return 0;
}
编译 & 运行
~/test/test_10
$ g++ -std=c++11 test3.cpp
~/test/test_10
$ ./a.out
++++++++++++=test_1
构造0xfca030
构造0xfca050
移动0xfca050
析构0
析构0xfca030
obj:
0xfca050
1
析构0xfca050
拷贝:
~/test/test_10
$ cat test3.cpp
#include <iostream>
using namespace std;
class A {
public:
int *pointer;
A() : pointer(new int(1))
{
std::cout << "构造" << pointer << std::endl;
}
A(const A& a) : pointer(new int(*a.pointer))
{
std::cout << "A(A& a)拷贝" << pointer << std::endl;
}
#if 0
A(A&& a) : pointer(a.pointer)
{
a.pointer = nullptr;
std::cout << "移动" << pointer << std::endl;
}
#endif
~A()
{
std::cout << "析构" << pointer << std::endl;
delete pointer;
}
};
A return_rvalue(bool test)
{
A a,b;
if (test) {
return a;
}
return b;
}
void test_1(void)
{
cout << "++++++++++++=" << __FUNCTION__ << endl;
A obj = return_rvalue(false);
std::cout << "obj:" << std::endl;
std::cout << obj.pointer << std::endl;
std::cout << *obj.pointer << std::endl;
}
int main(int argc, char *const argv[])
{
test_1();
return 0;
}
编译 & 运行
~/test/test_10
$ g++ -std=c++11 test3.cpp
~/test/test_10
$ ./a.out
++++++++++++=test_1
构造0x14c8030
构造0x14c8050
A(A& a)拷贝0x14c8070
析构0x14c8050
析构0x14c8030
obj:
0x14c8070
1
析构0x14c8070
|