C++ 为什么向量';s方法调整大小是否创建其他对象?
根据我的理解,C++ 为什么向量';s方法调整大小是否创建其他对象?,c++,vector,C++,Vector,根据我的理解,resize模板类vector的方法使用不带参数的构造函数创建一个新对象,然后使用复制构造函数克隆以前的对象。事实上,这一准则证明了这一点: #include <iostream> #include <vector> using namespace std; class A{ public: A(){ cout << "Appel constructeur !" << endl; cout &l
resize
模板类vector
的方法使用不带参数的构造函数创建一个新对象,然后使用复制构造函数克隆以前的对象。事实上,这一准则证明了这一点:
#include <iostream>
#include <vector>
using namespace std;
class A{
public:
A(){
cout << "Appel constructeur !" << endl;
cout << this << endl;
}
A(const A &a){
cout << "Appel constructeur de recopie" << endl;
cout << this << endl;
}
~A(){
cout << "Appel destructeur !" << endl;
}
};
int main() {
vector<A> t;
t.resize(2);
cout << t.size() << endl;
cout << &t[0] << endl;
cout << &t[1] << endl;
}
带有g++
的输出(它调用构造函数两次)
所以我的问题是:为什么要创建一个新对象然后销毁它?为什么创建的第一个对象的地址与其他对象相距甚远?您的编译器正在对您给出的代码执行一些奇怪的操作,我只能假设这是因为您使用的是C++11之前的版本。在中,C++11之前的
resize
方法将默认构造的对象作为第二个参数(如果未指定)。这将导致调用构造函数
如果当前大小小于count,则附加元素并使用值的副本初始化
这意味着默认构造的对象将被复制到向量中分配的两个新点中;这就是你在mingw身上看到的
在C++11及更高版本中,它应该只调用construct两次,destructor两次,不涉及副本。调用t.resize(2)
时,将两个“默认插入”对象添加到容器中,这些对象将调用构造函数。当向量超出范围并被销毁时,将调用析构函数
如果您改为执行以下操作:
t.resize(2);
t.resize(5);
现在,当且仅当内部阵列重新分配时,您将在第二次调整大小时获得一些副本或移动。前两个元素将从旧数组复制或移动到新数组。最后3个元素将默认插入到新数组中
至于对象内存地址的巨大差异,这实际上就是计算机中的工作方式。初始数组分配在动态内存的一个位置;然后,resize将获得一个新的内存位置,该位置可能就在旧位置的旁边,也可能完全位于其他位置
同时使用C++17和C++11
vector使用不带参数的构造函数创建新对象,然后使用复制构造函数克隆以前的对象。事实上,这一准则证明了这一点:
#include <iostream>
#include <vector>
using namespace std;
class A{
public:
A(){
cout << "Appel constructeur !" << endl;
cout << this << endl;
}
A(const A &a){
cout << "Appel constructeur de recopie" << endl;
cout << this << endl;
}
~A(){
cout << "Appel destructeur !" << endl;
}
};
int main() {
vector<A> t;
t.resize(2);
cout << t.size() << endl;
cout << &t[0] << endl;
cout << &t[1] << endl;
}
代码的输出并不能证明什么,它只显示了一个特定编译器在特定情况下所做的事情
在C++11之前,该标准规定新元素是通过insert
copy从临时初始化的值构造而创建的。因此地址不同,因为向量中的对象处于动态存储中,而临时对象处于临时(或自动)存储中
从C++11开始,它必须创建带有默认插入的新对象,这归结为默认分配器的值初始化
<>你的结果很可能是用旧编译器(或者在最近的编译器上不使用C++ 11模式)来解释的。调整大小方法在C++ 11之前有两个参数,所以你可能是用C++的旧版本编译的?您使用哪些编译器和编译器选项?在c++17中,应该有两个对构造函数的调用,两个对析构函数的调用。你能试试g++编译器吗?@ThunderPheonix,它不应该复制你给出的代码中的任何内容。请看一个更详细的示例。我猜想,
std::vector
的实现会创建元素类型的“默认”实例,然后将其复制到通过调用resize
创建的新索引中。我会在调试器中运行它,并在默认构造函数中设置一个断点,然后复制构造函数以查看发生了什么。自C++11以来的行为,是否有文档记录,您可以共享链接?@AbhishekChandel或cppreference.com(查找向量::resize函数)
t.resize(2);
t.resize(5);