[英]Behaviour of std::move operation in c++11
#include <string>
#include <iostream>
#include <utility>
struct A {
std::string s;
A() : s("test") {}
A(const A& o) : s(o.s) { std::cout << "move failed!\n"; }
A(A&& o) : s(std::move(o.s)) {}
A& operator=(const A&) { std::cout << "copy assigned\n"; return *this; }
A& operator=(A&& other) {
s = std::move(other.s);
std::cout << "move assigned\n";`enter code here`
return *this;
}
};
A f(A a) { return a; }
struct B : A {
std::string s2;
int n;
// implicit move assignment operator B& B::operator=(B&&)
// calls A's move assignment operator
// calls s2's move assignment operator
// and makes a bitwise copy of n
};
struct C : B {
~C() {}; // destructor prevents implicit move assignment
};
struct D : B {
D() {}
~D() {}; // destructor would prevent implicit move assignment
//D& operator=(D&&) = default; // force a move assignment anyway
};
int main()
{
A a1, a2;
std::cout << "Trying to move-assign A from rvalue temporary\n";
a1 = f(A()); // move-assignment from rvalue temporary
std::cout << "Trying to move-assign A from xvalue\n";
a2 = std::move(a1); // move-assignment from xvalue
std::cout << "Trying to move-assign B\n";
B b1, b2;
std::cout << "Before move, b1.s = \"" << b1.s << "\"\n";
b2 = std::move(b1); // calls implicit move assignment
std::cout << "After move, b1.s = \"" << b1.s << "\"\n";
std::cout << "Trying to move-assign C\n";
C c1, c2;
c2 = std::move(c1); // calls the copy assignment operator
std::cout << "Trying to move-assign D\n";
D d1, d2;
// d2 = std::move(d1);
}
執行a2 = std::move(a1)
語句時,行為與執行語句b2 = std::move(b1)
。 在下面的語句中,移動操作后b1.s
不會變空,而a1.s
在移動操作后變空。
誰能告訴那里究竟發生了什么?
關於C ++ 11和rvalue引用的一個很好的(和常量的)誤解是std::move
對一個對象(或者那個順序上的東西)做了一些事情。
它沒有。 std::move
實際上只是將其參數轉換為rvalue引用類型並返回該參數。 對對象所做的任何事情都發生在移動構造函數中,移動賦值運算符(等等)基於調用采用右值引用的版本的事實(而不是采用值或左值引用的版本)。
至於您提出的具體問題,至少根據您的代碼中的注釋,您似乎有一些誤解。 關於a2=std::move(a1);
說你正在做“從xvalue移動任務”。 那......充其量只是誤導。 xvalue是一個立即進行eXpire的值。 這幾乎是函數的返回值:
Foo &&bar() {
Foo f;
// ...
return f;
}
在這種情況下, bar()
是一個xvalue
因為當函數完成執行時, bar
返回對一個到期(超出范圍)的對象的rvalue引用。
至於你提出的具體問題,我懷疑它主要歸結為一個問題,即你的標准庫是否(以及如果確實如此)實現了std::string
的移動構造函數。 例如,當使用g ++(4.9.1)時,我得到了相同的結果 - b1.s
包含在用作移動源之前和之后的test
。 另一方面,如果我使用MS VC ++ 14 CTP,我會在移動前得到b1.s="test"
,移動后得到b1.s=""
。 雖然我沒有測試過,但我希望Clang的結果是一樣的。 簡而言之,看起來gcc的標准庫並沒有真正實現std::string
move
賦值/構造(至少從v 4.9開始 - 我還沒有看過5.0)。
通常移動賦值是作為std::string
的交換實現的,那么為什么字符串變為空,因為它總是用"test"
初始化?
在哪里看到a1.s
因為沒有打印而變空?
我在這里看不到任何奇怪的行為。 兩者都以同樣的方式對待。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.