![](/img/trans.png)
[英]Proper way to prevent deallocation using std::allocator and std::move
[英]using std::move to prevent copying
我有以下代码:
#include <iostream>
#include <vector>
struct A
{
std::vector<int> x;
A()
{
std::cout << "A()" << std::endl;
}
A(const A&)
{
std::cout << "A(const A&)" << std::endl;
}
~A()
{
std::cout << "~A()" << std::endl;
}
};
struct B : public A
{
std::vector<int> y;
B()
{
std::cout << "B()" << std::endl;
}
B(const A&a)
{
std::cout << "B(const A&)" << std::endl;
x = std::move(a.x);
y.resize(x.size());
}
B(const A&&a)
{
std::cout << "B(const A&&)" << std::endl;
x = std::move(a.x);
y.resize(x.size());
}
B(const B&)
{
std::cout << "B(const B&)" << std::endl;
}
~B()
{
std::cout << "~B()" << std::endl;
}
};
A ret_a()
{
A a;
a.x.resize(10);
return a;
}
int main()
{
std::cout << "section I" << std::endl << std::endl;
A a = ret_a();
B b(a);
std::cout << "a.x.size=" << a.x.size() << std::endl;
std::cout << std::endl << "section II" << std::endl << std::endl;
B b2(ret_a());
std::cout << "b.x.size=" << b.x.size() << std::endl;
std::cout << std::endl << "section III" << std::endl << std::endl;
return 0;
}
带输出(VS2013,发布版本)
section I
A()
A()
B(const A&)
a.x.size=10
section II
A()
A()
B(const A&&)
~A()
b.x.size=10
section III
~B()
~A()
~B()
~A()
~A()
为什么“ I部分”中的axsize()的大小为10? 我认为std :: move应该将所有数据从ax移到yx
为什么“第二节”两次调用构造函数A()? 我认为B(const A &&)可以防止A的过度复制
UPDATE
T&&
和const T&&
不是同一类型。 您几乎永远不需要const
rvalue引用-自从将其const
后就无法窃取其资源! x = std::move(ax);
B(const A&a)
const vector<int>&&
复制ax
因为std::move(ax)
的返回类型是const vector<int>&&
。 B(const A&&)
调用的默认构造A
因为它是衍生自A
,和成员初始化列表不会使试图构造基A
。 这是第二个A
呼叫。 为什么“ I部分”中的
axsize()
大小为10? 我认为std::move
应该将所有数据从ax
移到yx
这是因为B(const A&& a)
。 由于a
是该构造const
,因此您只能对其成员x
进行const
访问,并且在vector<T> const
上调用std::move
导致vector<T> const&&
不能绑定到vector
的move构造函数(采用vector<T>&&
参数)。 相反,它最终调用了复制构造函数,这使源对象保持不变。
为什么“第二节”两次调用构造函数
A()
? 我认为B(const A&&)
可以防止A
过度复制
第一个默认构造发生在ret_a()
的主体内。 第二种默认构造是B
的A
子对象的构造。 为了避免第二步,在成员初始化器列表中move
A
实例。
B(const A&&a)
: A(std::move(a))
{
std::cout << "B(const A&&)" << std::endl;
y.resize(x.size());
}
需要注意的是, move
实际上并没有导致的内容移动a
因同样的原因如上所述。 此外,即使修改签名B(A&& a)
不会导致内容a
移动由于用户提供拷贝构造函数和析构函数的定义,防止转移构造的隐代A
,它会被复制而不是。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.