[英]Weird c++ construct
我想為自己編譯openttd源。 它正在使用Squirell庫,由於鏈接器錯誤,我無法編譯該庫。 我查看了無法編譯的代碼,並且看到了我(和鏈接器:D)無法理解的怪異構造:
new ((void *)&_vals[i]) T(v._vals[i]);
我修改了代碼,現在看起來像這樣:
_vals[i] = *(new T(v._vals[i]));
我不知道我是否以良好的方式修改了代碼。 我希望我做到了。 游戲現在還沒有崩潰,所以也許它運行良好。
有人可以說為什么這個構造沒有做任何編譯時錯誤,而只是鏈接器錯誤? 這段代碼到底在做什么?
重要信息:我正在使用Visual Studio 2013。
這是標准位置new 。 你可能失蹤了
#include <new>
您所做的修改已導致內存泄漏。 以前,新對象是使用new放置到已經分配的內存中的。 現在,您使用new
創建一個對象,然后將其復制到_vals
。 但是,您永遠不會在原始文件上調用delete
。
這是新的位置 :
new (addr) T(...)
在內存地址addr
處構造T
對象。 在這里,它在地址&_vals[i]
構造它,也就是說,它覆蓋了對象_vals[i]
。 該地址被強制轉換為void*
,即原始內存地址。
當對象是不可變的或未實現賦值運算符時,有時會用於重建對象。 例如
A a(1);
...
a.~A(); // needed as otherwise a would not get destructed
new (&a) A(2);
...
在與舊對象相同的地址處創建一個新的A
對象,並使對該對象的引用和指針保持有效。
這是一個低級操作,可能會導致問題,即在不確定addr
是否適合該對象時進行內存對齊。
修改后的代碼將在堆上構造一個新對象,並將其分配給現有對象,然后將其泄漏。 在這種情況下,這不會泄漏內存:
_vals[i] = T(v._vals[i]);
鏈接器錯誤可能是因為沒有T::operator=(const T&)
,並且由於使用了新的位置。 (例如,如果T包含引用成員並且是不可變的)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.