為什么std::move()在這種情況下會導致 SEGFAULT?
#include <iostream>
struct Message {
std::string message;
};
Message * Message_Init(std::string message) {
Message * m = (Message*)calloc(1, sizeof(Message));
m->message = std::move(message);
return m;
}
int main() {
auto m = Message_Init("Hello");
return 0;
}
PS請不要問為什么Message不以通常的 C 方式構造。
uj5u.com熱心網友回復:
如果你真的想做這樣的事情,那么你可以使用placement new. 這允許您在已分配的記憶體塊中構造物件。
一些標準容器用于placement new管理其內部物件緩沖區。
但是,它確實增加了您放置的物件的解構式的復雜性。閱讀此處了解更多資訊:“安置新”有什么用途?
#include <iostream>
#include <memory>
struct Message {
std::string message;
};
Message * Message_Init(std::string message) {
void * buf = calloc(1, sizeof(Message));
Message * m = new (buf) Message(); // placement new
m->message = std::move(message);
return m;
}
int main() {
auto m = Message_Init("Hello");
m->~Message(); // Call the destructor explicitly
free(m); // Free the memory
return 0;
}
正如@selbie 建議的那樣,我添加了對解構式的顯式呼叫Message,以及free對釋放記憶體的呼叫。我相信呼叫free實際上應該指向最初回傳的緩沖區,calloc因為可能存在差異(所以free(buf)在這種情況下,但該指標在此處不可訪問)。
例如,如果您為多個物件分配一個緩沖區,那么呼叫free指向第二個物件的指標是不正確的。
uj5u.com熱心網友回復:
似乎對 C 中的賦值如何作業存在誤解。如果編譯器遇到涉及型別別的賦值操作,它會尋找一個稱為復制/移動賦值運算子的特殊函式。然后呼叫這個特殊函式來執行復制/移動。一般來說,左側和右側必須是初始化物件才能正常作業。
有一種特殊情況,允許使用未初始化的物件。這就是要復制/移動的物件的類具有簡單的復制/移動分配運算子的情況。然而,大多數標準庫類都不是簡單可復制/可移動的,尤其std::string是不能。
順便說一句,你打電話沒關系std::move。即使沒有它,它也將是未定義的行為。您必須在分配給它之前構造目標物件。您可以通過呼叫普通new運算子一次性分配和構造物件,或者通過分配空間并使用放置new在該空間中構造物件來做到這一點。
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/465380.html
上一篇:如何獲得查詢嵌套評論?
