我有一個我認為呼叫此 Test 結構的移動賦值運算子的簡單示例。運行它,它會呼叫移動建構式,然后在 Clang 的破壞時出現 seg 錯誤。在 MSVC 上,它作業正常。
我對這種行為有點困惑,因為我希望它用無引數建構式構造,然后呼叫移動賦值運算子。
#include <iostream>
struct Test
{
Test() : data(nullptr), dataCount(0) {}
Test(Test&& other)
{
std::cout << "mv cstr" << std::endl << std::flush;
delete[] data;
data = other.data;
other.data = nullptr;
dataCount = other.dataCount;
}
Test& operator=(Test&& other)
{
std::cout << "mv op" << std::endl << std::flush;
delete[] data;
data = other.data;
other.data = nullptr;
dataCount = other.dataCount;
return *this;
}
~Test()
{
std::cout << "dstr " << (void*)this << std::endl << std::flush;
delete[] data;
data = nullptr;
}
char* data;
size_t dataCount;
};
int main() {
Test test;
test.data = new char[3];
test.dataCount = 3;
Test newTest = std::move(test);
return 0;
}
如果我改為宣告然后分配,它當然可以按預期作業
int main() {
Test test;
test.data = new char[3];
test.dataCount = 3;
Test newTest;
newTest = std::move(test);
return 0;
}
我已經通讀了幾次 std::move、移動賦值運算子和移動建構式檔案,但我只是沒有得到這里有什么特別不同的地方,或者留給編譯器會在 MSVC 和 Clang 之間給出不同的行為。
我錯過了什么?
uj5u.com熱心網友回復:
將呼叫移動建構式,因為這正是您撰寫的代碼的目的:
Test newTest = std::move(test);
這里沒有發生移動賦值,因為一個新物件 ,newTest是從 . 右側的值構造的=。
由于您的移動建構式已呼叫delete[] data;且未data初始化,因此會發生未定義的行為。
我希望它用無引數建構式構造,然后呼叫移動賦值運算子。
如果您考慮到這一點,則不應該出現這種情況。編譯器不會采取這樣的迂回路線來構造物件,從而導致不必要的減速。
如果默認建構式很“重”,即通過昂貴的操作來構造物件怎么辦?移動建構式的重點是不必經過這一步,而只是從被移動的物件中“竊取”資料。
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/521000.html
