C++ New vs Malloc用于对象的动态内存数组

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)

谢谢.

Luc*_*ore 5

你不能.

如果你真的想要符合C++标准,你应该使用std::vector.

仅供参考,它可能比您想要实现的成本更高.如果你能这样做,new就会调用构造函数.但是既然你以后会修改对象,那么初始构造就没用了.


bam*_*s53 5

1) 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)

2)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以确保正确清理,并且它是异常安全的.手动执行这些操作很困难且容易出错.


3) 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现在指向足够用于Bullets 数组的存储.您可以在此存储中构造一个数组:

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.


4) std::vector

所以只需使用std::vector.