![](/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.