Tre*_*ent 3 c++ malloc new-operator dynamic-memory-allocation visual-c++
我有一个类子弹,它的构造有几个参数.但是,我使用动态内存阵列来存储它们.我正在使用C++,所以我想通过使用new运算符来分配内存来符合它的标准.问题是新的运算符在我分配数组时要求构造函数参数,这是我当时没有的.我可以使用malloc来获得正确的大小,然后在那里填写表单,但这不是我想要使用的:)任何想法?
pBulletArray = (Bullet*) malloc(iBulletArraySize * sizeof(Bullet)); // Works
pBulletArray = new Bullet[iBulletArraySize]; // Requires constructor arguments
Run Code Online (Sandbox Code Playgroud)
谢谢.
你不能.
如果你真的想要符合C++标准,你应该使用std::vector
.
仅供参考,它可能比您想要实现的成本更高.如果你能这样做,new
就会调用构造函数.但是既然你以后会修改对象,那么初始构造就没用了.
std::vector
一个std::vector
真正的C++方法是这样做的.
std::vector<Bullet> bullets;
bullets.reserve(10); // allocate memory for bullets without constructing any
bullets.push_back(Bullet(10.2,"Bang")); // put a Bullet in the vector.
bullets.emplace_back(10.2,"Bang"); // (C++11 only) construct a Bullet in the vector without copying.
Run Code Online (Sandbox Code Playgroud)
new []
运营商也可以这样做new
,但你真的不应该这样做.使用new
/ 手动管理资源delete
是一项高级任务,类似于模板元编程,因为它最好留给库构建者,他们将使用这些功能为您构建高效的高级库.事实上,为了正确地执行此操作,您基本上将实现内部std::vector
.
使用new
运算符分配数组时,数组中的每个元素都是默认初始化的.如果您将默认构造函数添加到Bullet
:
class Bullet {
public:
Bullet() {} // default constructor
Bullet(double,std::string const &) {}
};
std::unique_ptr<Bullet[]> b = new Bullet[10]; // default construct 10 bullets
Run Code Online (Sandbox Code Playgroud)
然后,当您拥有a的真实数据时,Bullet
可以将其分配给数组的其中一个元素:
b[3] = Bullet(20.3,"Bang");
Run Code Online (Sandbox Code Playgroud)
注意使用unique_ptr
以确保正确清理,并且它是异常安全的.手动执行这些操作很困难且容易出错.
operator new
该new
运营商除了为他们分配空间初始化它的对象.如果你想简单地分配空间,你可以使用operator new
.
std::unique_ptr<Bullet,void(*)(Bullet*)> bullets(
static_cast<Bullet*>(::operator new(10 * sizeof(Bullet))),
[](Bullet *b){::operator delete(b);});
Run Code Online (Sandbox Code Playgroud)
(请注意,unique_ptr
确保存储将被释放但不再存在.具体来说,如果我们在此存储中构造任何对象,我们必须手动销毁它们并以异常安全的方式执行此操作.)
bullets
现在指向足够用于Bullet
s 数组的存储.您可以在此存储中构造一个数组:
new (bullets.get()) Bullet[10];
Run Code Online (Sandbox Code Playgroud)
然而,数组结构再次使用每个元素的默认初始化,我们试图避免.
AFAIK C++没有指定任何定义良好的构造数组的方法而不构造元素.我想这很大程度上是因为这样做对于大多数(全部?)C++实现来说都是无操作的.因此,虽然以下技术上未定义,但在实践中它的定义非常明确.
bool constructed[10] = {}; // a place to mark which elements are constructed
// construct some elements of the array
for(int i=0;i<10;i+=2) {
try {
// pretend bullets points to the first element of a valid array. Otherwise 'bullets.get()+i' is undefined
new (bullets.get()+i) Bullet(10.2,"Bang");
constructed = true;
} catch(...) {}
}
Run Code Online (Sandbox Code Playgroud)
这将构造数组的元素而不使用默认构造函数.您不必构造每个元素,只需要构建您想要使用的元素.但是,当破坏元素时,你必须记住只破坏构造的元素.
// destruct the elements of the array that we constructed before
for(int i=0;i<10;++i) {
if(constructed[i]) {
bullets[i].~Bullet();
}
}
// unique_ptr destructor will take care of deallocating the storage
Run Code Online (Sandbox Code Playgroud)
以上是一个非常简单的案例.如果不将这些方法全部包含在类中,则可以非常轻松地使用此方法异常安全.将它包装在一个类中基本上相当于实现std::vector
.
std::vector
所以只需使用std::vector
.
归档时间: |
|
查看次数: |
6720 次 |
最近记录: |