使用容器中的新位置 我刚刚在C++中遇到了一些容器实现。该类使用内部缓冲区来管理其对象。这是一个没有安全检查的简化版本: template <typename E> class Container { public: Container() : buffer(new E[100]), size(0) {} ~Container() { delete [] buffer; } void Add() { buffer[size] = E(); size++; } void Remove() { size--; buffer[size].~E(); } private: E* buffer; int size; }; 模板类容器 { 公众: 容器():缓冲区(新的E[100]),大小(0){} ~Container(){delete[]buffer;} void Add(){buffer[size]=E();size++;} void Remove(){size--;缓冲区[size]。~E();} 私人: E*缓冲区; 整数大小; };
如果未自定义使用容器中的新位置 我刚刚在C++中遇到了一些容器实现。该类使用内部缓冲区来管理其对象。这是一个没有安全检查的简化版本: template <typename E> class Container { public: Container() : buffer(new E[100]), size(0) {} ~Container() { delete [] buffer; } void Add() { buffer[size] = E(); size++; } void Remove() { size--; buffer[size].~E(); } private: E* buffer; int size; }; 模板类容器 { 公众: 容器():缓冲区(新的E[100]),大小(0){} ~Container(){delete[]buffer;} void Add(){buffer[size]=E();size++;} void Remove(){size--;缓冲区[size]。~E();} 私人: E*缓冲区; 整数大小; };,c++,memory-management,placement-new,object-construction,object-destruction,C++,Memory Management,Placement New,Object Construction,Object Destruction,如果未自定义new/delete,则这将在Container()和~Container()中冗余地构造/销毁E对象。这似乎很危险 在Add()中使用placementnew是否是防止危险的冗余构造函数/析构函数调用的最佳方法(除了将类绑定到功能齐全的池之外) 当使用placementnew时,new char[sizeof(E)*100]是否是分配缓冲区的正确方法 这样做将冗余地构造/销毁E对象 看来是这样。newed数组已经应用了默认构造函数,delete[]也将为所有元素调用析构函数。实际上
new
/delete
,则这将在Container()
和~Container()
中冗余地构造/销毁E
对象。这似乎很危险
在Add()
中使用placementnew
是否是防止危险的冗余构造函数/析构函数调用的最佳方法(除了将类绑定到功能齐全的池之外)
当使用placementnew
时,new char[sizeof(E)*100]
是否是分配缓冲区的正确方法
这样做将冗余地构造/销毁E
对象
看来是这样。new
ed数组已经应用了默认构造函数,delete[]
也将为所有元素调用析构函数。实际上,Add()
和Remove()
方法除了维护size
计数器外,几乎没有添加其他内容
使用placement new时,new char[sizeof(E)*100]
是否是分配缓冲区的正确方法
最好选择已经为您处理所有内存问题的
使用placementnew
并自行管理内存需要注意许多问题(包括)
- 对齐
- 分配和使用的大小
- 毁灭
- 施工问题,如安置
- 可能的混叠
void*运算符new(std::size\u t count);
)将是内存分配的适当起点
如果不进一步解释代码的原始用途,那么对于管理容器中的元素,使用
std::vector
或std::array
将是更好的选择
这样做将冗余地构造/销毁E
对象
看来是这样。new
ed数组已经应用了默认构造函数,delete[]
也将为所有元素调用析构函数。实际上,Add()
和Remove()
方法除了维护size
计数器外,几乎没有添加其他内容
使用placement new时,new char[sizeof(E)*100]
是否是分配缓冲区的正确方法
最好选择已经为您处理所有内存问题的
使用placementnew
并自行管理内存需要注意许多问题(包括)
- 对齐
- 分配和使用的大小
- 毁灭
- 施工问题,如安置
- 可能的混叠
void*运算符new(std::size\u t count);
)将是内存分配的适当起点
如果不进一步解释代码的原始用途,则使用
std::vector
或std::array
将是管理容器中元素的更好选择。代码存在许多问题。
如果在调用Add()
之前调用Remove()
,则将对已销毁的对象执行赋值
否则,delete[]buffer
将调用数组中100个对象的析构函数。以前可能打过电话
以下是一个有效的程序:
#include <iostream>
int counter=0;
class Example {
public:
Example():ID(++counter){
std::cout<<"constructing "<<ID<<std::endl;
}
~Example(){
std::cout<<"destructing "<<ID<<std::endl;
ID=-1;
}
private:
int ID;
};
template <typename E> class Container
{
public:
Container() : buffer(new char [100*sizeof(E)]), size(0) {}
~Container() {
for(size_t i=0;i<size;++i){
reinterpret_cast<E*>(buffer)[i].~E();
}
delete [] buffer;
}
void Add() { new (buffer+sizeof(E)*size) E(); size++; }
void Remove() { reinterpret_cast<E*>(buffer)[--size].~E(); }
private:
void* buffer;
size_t size;
};
int main() {
Container<Example> empty;
Container<Example> single;
Container<Example> more;
single.Add();
more.Add();
more.Remove();
more.Add();
more.Add();
more.Remove();
return 0;
}
#包括
int计数器=0;
课例{
公众:
示例():ID(++计数器){
这段代码有很多问题。
如果在调用Add()
之前调用Remove()
,则将对已销毁的对象执行赋值
否则,delete[]buffer
将调用数组中100个对象的析构函数。这可能是以前调用过的
以下是一个有效的程序:
#include <iostream>
int counter=0;
class Example {
public:
Example():ID(++counter){
std::cout<<"constructing "<<ID<<std::endl;
}
~Example(){
std::cout<<"destructing "<<ID<<std::endl;
ID=-1;
}
private:
int ID;
};
template <typename E> class Container
{
public:
Container() : buffer(new char [100*sizeof(E)]), size(0) {}
~Container() {
for(size_t i=0;i<size;++i){
reinterpret_cast<E*>(buffer)[i].~E();
}
delete [] buffer;
}
void Add() { new (buffer+sizeof(E)*size) E(); size++; }
void Remove() { reinterpret_cast<E*>(buffer)[--size].~E(); }
private:
void* buffer;
size_t size;
};
int main() {
Container<Example> empty;
Container<Example> single;
Container<Example> more;
single.Add();
more.Add();
more.Remove();
more.Add();
more.Add();
more.Remove();
return 0;
}
#包括
int计数器=0;
课例{
公众:
示例():ID(++计数器){
std::Coutt这段代码有很多错误,但是在这段代码中没有放置-new
。不,不是。我从来没有说过会。我明白了,我当时误解了这个问题。我想你想在Remove()中解构buffer[size-1]
,或在解构之前减量。按照您在示例中的编写方式,您有一个一个一个的错误。@Mindrio:您是对的。由于提取示例而导致的错误。修复了它。此代码有很多错误,但此代码中没有放置-新的
。不,不是。我从来没有说过会。我明白了,我误解了那么问题来了。我想你应该在Remove()中解构buffer[size-1]
,或在解构之前递减。按照您的示例中的编写方式,您有一个off by one错误。@Mindrio:您是对的。由于提取示例而导致的错误。已修复。我不知道std::allocator
比简单的新位置提供了更强的保证。您能链接到某个引用吗?(cppreference,或standard中的部分)@YamMarcovic。这样做更容易,因为它已经为您完成了所有的艰苦工作。@Silicomancer.No,使用全局分配函数将是正确的::new(sizeof(E)*100);
@Niall O