我在使用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'
在这种情况下,T
的类型为JonsEngine::SceneNode
。
这是什么问题?为什么不T()
解析为SceneNode()
?为什么析构函数可以工作而不是构造函数?
答案 0 :(得分:5)
答案 1 :(得分: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);
}
是否也希望获得MSVC ++的声誉?
答案 2 :(得分:0)
您只需使用展示位置。
btw你使用析构函数是好的:
// 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在成员函数中使用lambdas时,您可能需要将this
传递到捕获列表中。
答案 3 :(得分:0)
为什么析构函数可以工作而不是构造函数?
因为析构函数属于实例而构造函数属于类型。
您无法调用具有该实例的构造函数,您必须使用该类型的名称来调用它。无论如何,你做的事情很奇怪。