Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/155.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ionic-framework/2.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++ 为什么向量';s方法调整大小是否创建其他对象?_C++_Vector - Fatal编程技术网

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);