C++ 新任务中以前的数据会发生什么变化?
考虑以下代码-C++ 新任务中以前的数据会发生什么变化?,c++,c++11,memory,vector,types,C++,C++11,Memory,Vector,Types,考虑以下代码- { int n = 3; n = 5; std::vector<int> v = { 1, 2, 3 .... 3242}; v = std::vector<int>{10000, 10001, 10002... 50000}; } { int n=3; n=5; 向量v={1,2,3..3242}; v=std::向量{10000,10001,10002…50000}; } 对于像int这样的基本数据类型,它可以简单
{
int n = 3;
n = 5;
std::vector<int> v = { 1, 2, 3 .... 3242};
v = std::vector<int>{10000, 10001, 10002... 50000};
}
{
int n=3;
n=5;
向量v={1,2,3..3242};
v=std::向量{10000,10001,10002…50000};
}
对于像int
这样的基本数据类型,它可以简单地用新值覆盖以前的内存位置,然后不使用它。但是,像std::vector
这样的类型会发生什么情况,其中先前值的长度可能与新赋值的长度不同
换句话说,当v被重新分配到新的{10000,10001,10002…50000}
值时,零件{1,2,3…3000}
会发生什么情况。它是否只是扔掉以前的值并将内部指针重新分配到新位置?或者,它是否尽可能用新数据覆盖以前的位置,并在分配较大时重新分配新内存,或者在分配较短时清除现有内存,从而保留初始向量的容量()
因为我在某个地方看到了这种类型的代码,所以在任何地方这比清除内容(v=vector{}
vs.clear()
)更可取吗
但是,像std::vector这样的类型会发生什么情况,其中先前值的大小可能与新赋值不同
我想你是说新数据数组的长度可能不同
std::vector
将其内部存储的问题与该存储的使用量分开。如果新数据具有更少、相同或更多的元素,则对象通常会重复使用相同的存储。这比简单地被覆盖要复杂得多,因为旧对象需要调用它们的析构函数(如果它们不是吊舱的话),但本质上是这样的。它们被(安全地)覆盖
如果您查看std::vector
的源代码,您将看到许多非常复杂的代码,涵盖了您提到的所有情况,还有一些您没有看到的
编写一个异常安全的、最优有效的向量并非易事
除非您对实现感兴趣(因为您想改进、维护它或只是好奇),否则std::vector
的行为文档足以说明您对它的期望
请特别注意哪些操作导致迭代器无效。这是一个有用的提示,表明内部对象正在存储中移动,或者可能会分配新的存储
链接:
但是,像std::vector这样的类型会发生什么情况,其中先前值的大小可能与新赋值不同
我想你是说新数据数组的长度可能不同
std::vector
将其内部存储的问题与该存储的使用量分开。如果新数据具有更少、相同或更多的元素,则对象通常会重复使用相同的存储。这比简单地被覆盖要复杂得多,因为旧对象需要调用它们的析构函数(如果它们不是吊舱的话),但本质上是这样的。它们被(安全地)覆盖
如果您查看std::vector
的源代码,您将看到许多非常复杂的代码,涵盖了您提到的所有情况,还有一些您没有看到的
编写一个异常安全的、最优有效的向量并非易事
除非您对实现感兴趣(因为您想改进、维护它或只是好奇),否则std::vector
的行为文档足以说明您对它的期望
请特别注意哪些操作导致迭代器无效。这是一个有用的提示,表明内部对象正在存储中移动,或者可能会分配新的存储
link:这两种方法都可以,这取决于vector
的实现者,您正在使用移动分配。该标准本质上要求丢弃现有数据,销毁其所有元素,并从右侧移动新数据。这是因为操作必须与受体载体的当前大小成线性关系,并且与供体的大小无关。此外,所有指向施主元素的引用、指针和迭代器必须保持有效(但现在引用目标中的元素)——这也排除了类似“从右向左复制元素”的情况。许多事情发生在这第四行,但您可能对调用感兴趣。您可以使用调试器单步执行此函数,以查看std::vector
的实现中到底发生了什么。在debug build中执行此操作,因为发布版本可能会优化所有内容。它可以执行这两种操作中的任何一种,这取决于vector
的实现者,您正在使用移动分配。该标准本质上要求丢弃现有数据,销毁其所有元素,并从右侧移动新数据。这是因为操作必须与受体载体的当前大小成线性关系,并且与供体的大小无关。此外,所有指向施主元素的引用、指针和迭代器必须保持有效(但现在引用目标中的元素)——这也排除了类似“从右向左复制元素”的情况。许多事情发生在这第四行,但您可能对调用感兴趣。您可以使用调试器单步执行此函数,以查看std::vector
的实现中到底发生了什么。在调试版本中这样做,因为发布版本可能会优化所有内容。虽然您的答案通常是正确的(“不要担心”),但OP给出的具体示例是移动任务。移动分配保证了复杂性(如果分配器比较相等,复杂性与rhs的大小无关),这意味着移动分配必须“丢弃”