2015-09-07 99 views
0

我在使用for_each()時遇到問題,並在每個元素上調用構造函數/析構函數。std :: for_each()並調用構造函數/析構函數

僅供參考,mBegin指向數組的起始位置,mEnd超出最後一個元素,mCapacity指向分配的內存末尾。

template <typename T> 
void IDMapTree<T>::Grow() 
{ 
    const size_t prevSize = mCapacity - mBegin; 
    const size_t newSize = prevSize != 0 ? static_cast<size_t>(1.5f * prevSize) : 1; 
    T* newBuffer = static_cast<T*>(mAllocator.Allocate(newSize)); 

    // initialize new buffer elements with copy constructor using old elements 
    uint32_t itemIndex = 0; 
    std::for_each(newBuffer, newBuffer + prevSize, [&](T& item) { item.T(*(mBegin + itemIndex++)); }); 
    // destruct all old elements 
    std::for_each(mBegin, mEnd, [](T& item) { item.~T(); }); 


    // ... 
} 

這部分編譯罰款:

std::for_each(mBegin, mEnd, [](T& item) { item.~T(); }); 

但這不到風度:

std::for_each(newBuffer, newBuffer + prevSize, [&](T& item) { item.T(*(mBegin + itemIndex++)); }); 

甚至沒有,如果我使用默認的構造函數是這樣的:

std::for_each(newBuffer, newBuffer + prevSize, [](T& item) { item.T(); }); 

編譯器(VS2013)說:

error C2039: '__this' : is not a member of 'JonsEngine::SceneNode' 
error C2039: 'T' : is not a member of 'JonsEngine::SceneNode' 

在這種情況下,TJonsEngine::SceneNode類型。

這裏有什麼問題?爲什麼dosn't T()解析爲SceneNode()?爲什麼析構函數可以工作,而不是構造函數?

+2

您正試圖調用已存在對象的構造函數嗎? o.0 –

+0

你爲什麼明確地調用析構函數?您是否使用展示位置新構建了這些元素? – MatthewRock

+1

只需使用'std :: vector'作爲存儲。 –

回答

0

不喜歡它的STL做它 - 通過未初始化的內存塊爲void* ptr,然後

::operator new(ptr) T(item)

item應該爲const引用傳遞。 (或更好 - 移動)

char* newBuffer = static_cast<char*>(mAllocator.Allocate(newSize)); 
if (newSize % sizeof(T) != 0){ 
    throw std::runtime_error("memory is not alligned"); 
} 
for (size_t i = 0; i< newSize; i += sizeof(T)){ 
    ::operator new((void*)ptr) T(item) 
} 

你也應該移動對象的副本,而不是和刪除舊的。這也將使你免於破壞舊物件的需要。

編輯: 我不明白爲什麼downvote時,這是調用預分配的內存塊上的任何構造函數的正確方法。這是MSVC++ Allocator::construct功能,做同樣的事情

void construct(_Ty *_Ptr, const _Ty& _Val) 
    { // construct object at _Ptr with value _Val 
    ::new ((void *)_Ptr) _Ty(_Val); 
    } 

想downvote MSVC++的聲譽呢?

+0

他顯然是在做某種(奇怪的)分配器。認爲這個代碼塊是在'allocator :: construct'中,突然我們不會對它產生負面影響。 –

+0

也,我不明白你怎麼能判斷什麼被認爲是一個很好的解決方案,當你甚至不知道OP正在嘗試解決什麼問題 –

0

你只需要使用新的位置。

順便說一句你的析構函數的使用是好的:

// destruct all old elements 
std::for_each(mBegin, mEnd, [](T& item) { item.~T(); }); 

表達item.~T();是顯式調用析構函數的正確方法。

你不能以這種方式調用構造函數。

所以,放置新的可能是要走的路:

std::for_each(newBuffer, newBuffer + prevSize, [](T& item) { new (&item) T(); }); 

BTW一個成員函數中使用Lambda表達式時,則可能需要通過this到捕獲列表。

0

爲什麼析構函數工作而不是構造函數?

因爲析構函數屬於實例而構造屬於類型。

您不能調用具有實例的構造函數,您必須使用該類型的名稱調用它。無論如何,你正在做一些奇怪的事情。

相關問題