2016-03-15 70 views
2

我無法理解在C++ 11中移動的函數。C++ 11:如何理解函數移動

here,我得到了如下的事情:

雖然注意到 - 在標準庫 - 移動意味着 移動,從對象是在一個有效的,但不確定狀態離開。其中 表示經過這樣的操作後,移動對象 的值應該只銷毀或分配新值;訪問它 否則會產生未指定的值。

在我看來,移動()後,移動的對象已被「清除」。不過,我已經做了如下測試:

std::string str = "abcd"; 
std::move(str); 
std::cout<<str; 

我在我的屏幕上了abcd
那麼str被銷燬了嗎?如果是這樣,我可以得到abcd,因爲我只是幸運?或者我誤解了功能move

此外,當我讀到C++入門,我有這樣的代碼:

class Base{/* ... */}; 
class D: public Base{ 
public: 
    D(D&& d): Base(std::move(d)){/* use d to initialize the members of D */} 
}; 

我現在很困惑。如果函數move將清除該對象,則參數d將會清除,我們如何「使用d初始化D的成員」?

+1

你很幸運。或者不幸,取決於你的觀點。 –

回答

1

std :: move不會移動任何東西。 std :: move只是一個執行強制轉換的函數模板。的std ::無條件移動蒙上它的參數到右值,

std::move(str); 

有了這個表達你只是在做類型轉換的左值到右值。

程序中的小修改可以更好地理解。

std::string str = "abcd"; 
std::string str1 = std::move(str); 
std::cout<<str<<std::endl; 
std::cout<<str1<<std::endl; 

str左值類型轉換到右值由std::movestd::string = std::move(str); =>這個表達式調用string move constructor其中資源的實際竊取取放置。 str資源(abcd)被壓平並打印出空串。

下面是移動功能的示例實現。請注意,它不是標準庫的完整實現。

template<typename T> // C++14; still in 
decltype(auto) move(T&& param) // namespace std 
{ 
using ReturnType = remove_reference_t<T>&&; 
return static_cast<ReturnType>(param); 
} 

將std :: move應用於一個對象告訴編譯器該對象有資格從中移出。它投向右值。

class Base{/* ... */}; 
class D: public Base{ 
public: 
    D(D&& d): Base(std::move(d)){/* use d to initialize the members of D */} 
}; 

Base(std::move(d))它會做向上移動只移動基類的一部分。

這裏有一個更有趣的事情要爲你學習。如果你不調用std::move之類的基類析構函數,就像D(D&& d): Base(d)那麼d將被認爲是左值並拷貝所涉及的Base類的構造函數而不是移動構造函數。請參閱詳細信息Move constructor on derived object

4

std::move實際上並不是什麼。這大致類似於轉換表達式,因爲返回值是原始對象,但是處理方式不同。

更確切地說,std::move返回對象的形式,該形式適合其資源被「偷」出於某種其他目的。原始對象或多或少地保持有效(你只應該爲它做一些特殊的事情,雖然這主要是一個約定的問題,並不一定適用於非標準庫對象),但被盜的資源沒有更長時間屬於它,通常不會再被它引用。

但是! std::move本身不做偷竊。它只是設置偷竊被允許的東西。既然你沒有對結果做任何事情,更不用說可以利用機會的東西,什麼都不會被偷。