Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何判断std::vector是否调整了自身大小,以及如何解释指向向量内值的指针不再有效?_C++_Arrays_Pointers_Memory Management_Stdvector - Fatal编程技术网

C++ 如何判断std::vector是否调整了自身大小,以及如何解释指向向量内值的指针不再有效?

C++ 如何判断std::vector是否调整了自身大小,以及如何解释指向向量内值的指针不再有效?,c++,arrays,pointers,memory-management,stdvector,C++,Arrays,Pointers,Memory Management,Stdvector,我知道,如果调整std::vector的大小(我相信只会增加大小),那么该向量的内存位置将被重新定位,以便在堆内存中找到一个实际适合新大小的新位置。在这种情况下,如果指针A、B和C以前指向向量中的元素,它们将指向旧的、未分配的内存位置,并且不再有效 我想知道A:如果这样的事件发生时可以得到通知,而不需要我显式地管理std::vector的大小,B:如何处理指针不再引用内存中的正确位置 B部分有点模糊,所以我将缩小我想要使用这种行为的用例范围。在我的情况下,我有一个类,它维护一个对象向量,对象向量

我知道,如果调整std::vector的大小(我相信只会增加大小),那么该向量的内存位置将被重新定位,以便在堆内存中找到一个实际适合新大小的新位置。在这种情况下,如果指针A、B和C以前指向向量中的元素,它们将指向旧的、未分配的内存位置,并且不再有效

我想知道A:如果这样的事件发生时可以得到通知,而不需要我显式地管理std::vector的大小,B:如何处理指针不再引用内存中的正确位置

B部分有点模糊,所以我将缩小我想要使用这种行为的用例范围。在我的情况下,我有一个类,它维护一个对象向量,对象向量内部有几个指针,如下所示:

class MultiPointer{
public:
    Type1* t1;
    Type2* t2;
    Type3* t3;
    MultiPointer(Type1*t1, Type2*t2, Type3*t3);
};
...
// attempt to create singleton pattern to make pool of each object type for each class
class Type1{
...
    static vector<Type1> arr1 = ...
}
class Type2{
...
    static vector<Type2> arr2 = ...
}
class Type3{
...
    static vector<Type3> arr3 = ...
}
...

//note, would actually use CRTP to make sure I don't have to type out static vector<TypeN> each time

MultiPointer a(&arr1[0], arr2[0], arr3[0]);
MultiPointer b(&arr1[1], arr2[1], arr3[1]);
MultiPointer c(&arr1[2], arr2[2], arr3[2]);
std::vector<MultiPointer> mpv= {a,b,c};
... insertions into arr1,2,3 ...
//How do I make sure that a, b, and c still point to the same types? 
然后我会检查大小是否在需要时更改,如果大小更改,我会检查指针是否相同(或者只检查指针是否相同)

如果我注意到地址发生了变化,我会使用指针arhimetic来找到旧指针相对于新地址的正确位置

// in MultiPointer
...
// if pointers don't match for arr1
t1 = (arr1ptrcpy - t1) + Type1::arr1[0];
...
// if pointers don't match for arr2
t2 = (arr2ptrcpy - t2) + Type2::arr2[0];
...
// if pointers don't match for arr3
t2 = (arr3ptrcpy - t3) + Type3::arr3[0];
虽然我可以通过句柄来完成这一切,但这需要运行时开销来进行指针反引用,因为我会有很多指针。在这种情况下,我将检查向量更改的频率远低于取消引用指针。如果这可以通过迭代器实现,而每个迭代器没有额外的内存开销,那么我也愿意看看如何实现

编辑:我想提供更多关于我的实际应用程序试图实现什么/它是如何构造的信息。在实际用例中,有许多类型的多接口,其中一些引用相同的对象,但有不同的指针类型(因此首先需要有指针),并且它们引用的对象也在多接口上下文之外的其他地方使用

在我的实际应用程序中,“MultiPointer”充当一组对象,这些对象具有附加到这些组的不同功能。例如,您可能有一个PhysicsMultiInter,它有一个位置*和速度*,还有一个GraphicMultiInter,它有一个显示图像*和一个位置*。它们都将指向此处的同一位置对象

第二次编辑:


我应该提到我需要类型向量中的所有元素都在连续内存中,如果不是这样的话,我甚至不会为这整个考验而烦恼,因为我只需要指向堆对象的指针,而堆对象不会改变位置

要在向量中的内部指针发生更改时收到通知,可以包装
std::vector
。您需要钩住函数
push_-back()
emplace_-back()
resize()
shorn_-to_-fit()
(只需禁用该函数),
reserve()
,以及
insert()
。只需在前后检查
data()
,并在发生更改时调用回调,就很容易了

答:如果有可能在此类事件发生时收到通知,而无需我明确管理std::vector的大小

没有

你可以很容易地知道它什么时候会发生,但你不能在事后告诉它什么时候发生<代码>向量重新分配仅在您将
向量
的大小增加到超过其当前
容量
(或者您调用
收缩以适应
)时发生。因此,如果在
向量中插入4项,那么如果容量大小为4或更多,它将不会重新分配自身

现在,您可以使用这个事实为插入函数构建包装函数/对象,它将检查插入前后的容量,并返回容量是否已更改(如果发生重新分配,则必须增加容量)

然而,更好的解决方法是简单地。。。不要让它发生。使用
reserve
功能使容量足够大,这样您就不需要重新分配。通过这样做,您将不必关心重置指针之类的事情

请注意,以上内容仅涵盖由于重新分配而导致的指针无效。如果在
向量的中间插入对象,但仅在插入点和所有后续元素处插入指向该元素的指针/引用,则指针和引用将无效

B:如何处理指针不再引用内存中的正确位置

不要使用指针。相反,使用索引。除非插入到
向量的中间
;在这方面我无能为力


如果索引不能为您工作,那么我将重新考虑使用
vector
。如果您非常需要元素的稳定性,那么
list
forward\u list
似乎是更适合此工作的工具。或者,如果您可以访问Boost,
Boost::stable_vector

为什么不直接访问向量成员,而不是使用指针指向向量成员?这是什么意思?直接引用向量成员,因为只有一个包含3个成员的对象,而不是指向成员的3个指针?你的意思是只要有直线型的物体?在我的实际应用程序中,Type1->3被创建并在其他地方使用,然后再添加到我的实际应用程序中,相当于MultiInter。在实际应用中,有多种类型的多接口,它们可能指向相同的对象,但具有不同的指针类型组合。您不应持有指向向量内部位置的指针。您可以保留指向向量中引用的对象的指针,因为它们的位置不会因向量的大小而改变
//ie in main
if(arr1ptrcpy != &(Type1::arr1[0])){
// for each multi pointer in mpv, adjust pointers for arr1. 
...
}
// in MultiPointer
...
// if pointers don't match for arr1
t1 = (arr1ptrcpy - t1) + Type1::arr1[0];
...
// if pointers don't match for arr2
t2 = (arr2ptrcpy - t2) + Type2::arr2[0];
...
// if pointers don't match for arr3
t2 = (arr3ptrcpy - t3) + Type3::arr3[0];