C++ 包含vecto的对象的动态分配

C++ 包含vecto的对象的动态分配,c++,vector,dynamic,allocation,C++,Vector,Dynamic,Allocation,我试着这样做: #include <iostream> #include <vector> using namespace std; struct test{ vector<int> tab; }; int main(){ test* obj2; obj2 = (test*) malloc(sizeof(test)); obj2->tab.push_back(1); obj2->tab.push_

我试着这样做:

#include <iostream>
#include <vector>

using namespace std;

struct test{
    vector<int> tab;
};

int main(){
    test* obj2;
    obj2 = (test*) malloc(sizeof(test));


    obj2->tab.push_back(1); 
    obj2->tab.push_back(2);
    for(int i=0;i<2;i++){
        cout<<obj2->tab[i]<<" ";
    }
}
#包括
#包括
使用名称空间std;
结构测试{
向量标签;
};
int main(){
测试*obj2;
obj2=(测试*)malloc(sizeof(测试));
obj2->tab.推回(1);
obj2->tab.向后推(2);
对于(int i=0;i
它起作用了

不,它没有。这是不确定的行为似乎起作用

但我不明白为什么

为了理解这(似乎)起作用的原因,我们必须看看
std::vector
的结构。一个实现可以使用3个指针:

  • 分配内存的开始
  • 已用内存结束
  • 分配内存结束
现在通过
malloc()分配一些字节
并将它们解释为一个包含这3个指针的类。如果我们假设一个指针为4字节大,则分配12个字节,并将前4个字节解释为指向已分配内存开始的指针,后4个字节解释为指向已用内存结束的指针,最后4个字节解释为指向已分配内存结束的指针

如果分配的内存恰好包含合理的值,这可能是有效的。但是它确实是未定义的行为。例如,C++中包含所有的零点,这导致所有三个指针都是代码> NulLPTR < /代码>,这可能也是构造函数所做的。

但是在VisualStudio中,内存没有初始化为零,这导致所有三个指针的随机值,从而导致segfault

那么,为什么这(似乎)起作用呢?因为你分配的内存包含了合理的值,这纯粹是运气使然

我要求一些空向量的内存

不,您只需分配内存并将其解释为一个向量。向量为空(甚至可以工作)只是幸运,如上所述。碰巧向量在调用构造函数后会以相同的状态结束

但是,我在向量中添加了一些东西,所以obj2占用的内存增加了,不是吗

不,它不是。任何对象的大小在编译时都是已知的和固定的。一个
std::vector
只管理堆内存,例如动态分配的内存。因此它不会增加它自己的大小,也不会增加包含它的结构的大小,而只是增加它所管理的内存的大小

这仍然是一件好事吗

不,绝对不是。如果您需要动态内存,请使用容器、智能指针或至少
new

它起作用了

不,它没有。这是不确定的行为似乎起作用

但我不明白为什么

为了理解这(似乎)起作用的原因,我们必须看看
std::vector
的结构。一个实现可以使用3个指针:

  • 分配内存的开始
  • 已用内存结束
  • 分配内存结束
现在通过
malloc()分配一些字节
并将它们解释为一个包含这3个指针的类。如果我们假设一个指针为4字节大,则分配12个字节,并将前4个字节解释为指向已分配内存开始的指针,后4个字节解释为指向已用内存结束的指针,最后4个字节解释为指向已分配内存结束的指针

如果分配的内存恰好包含合理的值,这可能是有效的。但是它确实是未定义的行为。例如,C++中包含所有的零点,这导致所有三个指针都是代码> NulLPTR < /代码>,这可能也是构造函数所做的。

但是在VisualStudio中,内存没有初始化为零,这导致所有三个指针的随机值,从而导致segfault

那么,为什么这(似乎)起作用呢?因为你分配的内存包含了合理的值,这纯粹是运气使然

我要求一些空向量的内存

不,您只需分配内存并将其解释为一个向量。向量为空(甚至可以工作)只是幸运,如上所述。碰巧向量在调用构造函数后会以相同的状态结束

但是,我在向量中添加了一些东西,所以obj2占用的内存增加了,不是吗

不,它不是。任何对象的大小在编译时都是已知的和固定的。一个
std::vector
只管理堆内存,例如动态分配的内存。因此它不会增加它自己的大小,也不会增加包含它的结构的大小,而只是增加它所管理的内存的大小

这仍然是一件好事吗


不,绝对不是。如果您需要动态内存,请使用容器、智能指针或至少是
new
Oops,创建动态对象和使用malloc分配其内存之间有很大的区别:对象的构造

在您的代码中,永远不会构造
test
对象,因此,向量也不是:您的代码使用未初始化的对象调用未定义的行为

如果您被迫使用C模块提供的内存区域,则应考虑使用新的放置方式来完全构造对象:

test* obj2;
obj2 = (test*) malloc(sizeof(test));     // obj2 points to uninitialized memory

obj2 = new((void *) obj2) test;          // construct an object in the allocated memory
                                         //  including its subobjects (here the vector member)

obj2->tab.push_back(1);                  // no longer UB...

面向对象,创建动态对象和使用malloc分配其内存之间有很大区别:对象的构造

在您的代码中,永远不会构造
test
对象,因此,向量也不是:您的代码使用未初始化的对象调用未定义的行为

如果您被迫使用C模块提供的内存区域,则应考虑使用新的放置方式来完全构造对象:

test* obj2;
obj2 = (test*) malloc(sizeof(test));     // obj2 points to uninitialized memory

obj2 = new((void *) obj2) test;          // construct an object in the allocated memory
                                         //  including its subobjects (here the vector member)

obj2->tab.push_back(1);                  // no longer UB...

不要在C++中使用<代码> MalOC/,使用<代码>新< /COD>。当你使用<代码> MalOC/<代码>时,你会要求一些内存中不包含任何东西,并且试图使用一个不存在的对象有未定义的行为。我忘了说为什么我使用Maloc,我现在就改变它。