C++ 关于存储类的去向

C++ 关于存储类的去向,c++,C++,假设我有一个向量,它的类型是structpoint,请参见下面的代码片段。一个函数向其中添加两个点。因为这里的点是本地初始化的。是否存在函数返回时无法访问点的问题/担忧?向量容器中是否有copy操作,如果有,这些数据结构实际存储在哪里?成堆 struct point { int x; int y; string name; }; vector<point> pointvec; int addpoints() { point p1 {2, 3, "p

假设我有一个向量,它的类型是struct
point
,请参见下面的代码片段。一个函数向其中添加两个点。因为这里的点是本地初始化的。是否存在函数返回时无法访问点的问题/担忧?向量容器中是否有
copy
操作,如果有,这些数据结构实际存储在哪里?成堆

struct point {
    int x;
    int y;
    string name;
};

vector<point> pointvec;

int addpoints() {
    point p1 {2, 3, "point 1"};
    point p2 {4, 4, "point 2"};

    pointvec.push_back(p1);
    pointvec.push_back(p2);

}
结构点{
int x;
int-y;
字符串名;
};
向量点向量;
int addpoints(){
点p1{2,3,“点1”};
点p2{4,4,“点2”};
点向量推回(p1);
点向量推回(p2);
}

矢量开始时没有分配内存。在第一次
推回过程中
,它为该元素分配足够的空间,并复制传入的点。在下一次
推回过程中,它为两个元素重新分配了足够的空间,并将上一个元素的副本移动到新内存中,然后复制第二个点。如果您再次
向后推
,它将为(通常)4个元素分配足够的空间,移动其副本,然后复制新的

对这些操作的复杂性有标准化的限制(摊销不变),要求分配的向量内存与向量当前长度成比例增长。它必须按比例增长的原因是现有元素的移动(如上文所述的第二个
push_back
)。这意味着重新分配的复杂性随着向量的长度而增长,摊销常量插入将不再是摊销常量。为了抵消这一点,重新分配必须与长度成比例。这一比例通常是当前长度的2倍,尽管我不认为这是必须的

示例中的内存是在堆上分配的,但是如果要为向量提供不同的分配器类型,则可以在分配器允许的任何位置分配它

因此,您的示例是安全的,但速度很慢,并且通常需要在堆上为该简单函数分配2次。更好的解决方案是使用只分配一次堆内存的
reserve
方法预先分配必要的内存

int addpoints() {
    point p1 {2, 3, "point 1"};
    point p2 {4, 4, "point 2"};

    pointvec.reserve(2);

    pointvec.push_back(p1);
    pointvec.push_back(p2);
}

vector
在没有分配内存的情况下启动。在第一次
推回过程中
,它为该元素分配足够的空间,并复制传入的点。在下一次
推回过程中,它为两个元素重新分配了足够的空间,并将上一个元素的副本移动到新内存中,然后复制第二个点。如果您再次
向后推
,它将为(通常)4个元素分配足够的空间,移动其副本,然后复制新的

对这些操作的复杂性有标准化的限制(摊销不变),要求分配的向量内存与向量当前长度成比例增长。它必须按比例增长的原因是现有元素的移动(如上文所述的第二个
push_back
)。这意味着重新分配的复杂性随着向量的长度而增长,摊销常量插入将不再是摊销常量。为了抵消这一点,重新分配必须与长度成比例。这一比例通常是当前长度的2倍,尽管我不认为这是必须的

示例中的内存是在堆上分配的,但是如果要为向量提供不同的分配器类型,则可以在分配器允许的任何位置分配它

因此,您的示例是安全的,但速度很慢,并且通常需要在堆上为该简单函数分配2次。更好的解决方案是使用只分配一次堆内存的
reserve
方法预先分配必要的内存

int addpoints() {
    point p1 {2, 3, "point 1"};
    point p2 {4, 4, "point 2"};

    pointvec.reserve(2);

    pointvec.push_back(p1);
    pointvec.push_back(p2);
}

是的,
被复制或移动到向量的内部数组中。因此,在函数返回后访问它们应该没有问题。嗯。。。“移动”或“复制”?-在我看来,内存管理似乎有所不同。也许没关系?。对于向量的用户(即:你)来说,它“无关紧要”,向量
处理其内存本身(这是它优于使用C样式数组的主要原因之一)。是的,
被复制或移动到向量的内部数组中。因此,在函数返回后访问它们应该没有问题。嗯。。。“移动”或“复制”?-在我看来,内存管理似乎有所不同。也许没关系?。对于向量的用户(即:你)来说,它“无关紧要”
vector
处理其内存本身(这是它优于使用C风格数组的主要原因之一)。不能保证数据存储在堆上。不能保证会有一堆。小麻烦。不能保证数据存储在堆上。不能保证存在堆。