Std::for_each()和调用构造函数/析构函数
std::for_each() and calling constructors/destructors
我在使用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()
?为什么析构函数可以工作,而构造函数却不行?
您可以使用std::uninitialized_copy()
。
像stl那样做-将未初始化的内存块作为void* ptr
传递,然后
::operator new(ptr) T(item)
item
应该作为const引用传递。(或更好- move)
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)
}
您还应该移动对象,而不是复制和删除旧的对象。这也将使您不必销毁旧的对象。
编辑:当这是在预分配的内存块上调用任何构造函数的正确方法时,我不明白为什么要投票。这是msvc++ Allocator::construct
函数,它做同样的事情
void construct(_Ty *_Ptr, const _Ty& _Val)
{ // construct object at _Ptr with value _Val
::new ((void *)_Ptr) _Ty(_Val);
}
也想贬低msvc++的声誉吗?
你只需要使用位置new。
顺便说一句,你使用析构函数是没问题的:
// destruct all old elements
std::for_each(mBegin, mEnd, [](T& item) { item.~T(); });
表达式item.~T();
是显式调用析构函数的正确方法。
不能这样调用构造函数
因此,位置new可以是一种方法:
std::for_each(newBuffer, newBuffer + prevSize, [](T& item) { new (&item) T(); });
顺便说一句,当在成员函数中使用lambdas时,您可能需要将this
传递到捕获列表中。
为什么析构函数可以工作,而构造函数不行?
因为析构函数属于实例而构造函数属于类型。
不能使用实例来调用构造函数,必须使用类型的name来调用它。无论如何,你做了一些奇怪的事情。
相关文章:
- 在c++中使用向量时,如何调用构造函数和析构函数
- C++:考虑但不调用构造函数的特殊性
- 对象实例化调用构造函数的次数太多
- 我使用向量来创建类对象列表.初始化向量时如何使用参数调用构造函数?
- C ++:通过大括号调用构造函数?
- 不能调用构造函数
- 赋值 boost::intrusive_ptr 而不调用构造函数?
- 在模板化类的构造函数中调用构造函数
- 如何为 std::vector 分配内存,然后稍后为某些元素调用构造函数?
- 为什么从另一个构造函数内部调用C++构造函数不修改类变量?
- 静态 std::map instatiation 在类的方法中调用构造函数吗?
- 有没有一种简单的方法可以在对象向量上调用构造函数?
- 我不明白在这个例子中什么时候调用构造函数
- 调用c++构造函数的不同方法
- 调用构造函数与将内联常量定义为默认参数
- 如何通过 Rust FFI 调用C++构造函数?
- "new"运算符是否总是调用构造函数?
- 无法调用构造函数
- 使用 "()" 调用构造函数不同于"{}"
- 确定是调用构造函数还是强制转换运算符的因素