2015-09-07 107 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

为什么析构函数工作而不是构造函数?

因为析构函数属于实例而构造属于类型。

您不能调用具有实例的构造函数,您必须使用该类型的名称调用它。无论如何,你正在做一些奇怪的事情。