Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/dart/3.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++ 第一次破坏来自哪里?_C++ - Fatal编程技术网

C++ 第一次破坏来自哪里?

C++ 第一次破坏来自哪里?,c++,C++,我试图练习以下代码: #include <iostream> #include <vector> using namespace std; class A { public: virtual void f(){cout<<"A"<<endl;} virtual ~A(){cout<<"destruct A"<<endl;} }; int main() { A o1,o2; vector <

我试图练习以下代码:

#include <iostream>
#include <vector>

using namespace std;

class A
{
public:
   virtual void f(){cout<<"A"<<endl;}
   virtual ~A(){cout<<"destruct A"<<endl;}
};

int main()
{
   A o1,o2;
   vector <A > O;
   O.push_back(o1);
   cout<<"1"<<endl;
   O.push_back(o2);

cout<<"test"<<endl;
return 0;
}

弄不清楚第一个析构函数来自何处。

让构造函数和析构函数打印对象的内存地址,这样就可以跟踪对象的生存期:

virtual void f() { cout << "A: " << std::hex << this << endl; }
virtual ~A(){ cout << "destruct A: " << std::hex << this << endl; }

virtual void f(){cout您的向量在第二次调用push_back时重新分配了其内存缓冲区。这要求将其中的对象复制到新缓冲区,并销毁原始对象


如果您调用
O.reserve(2)
在插入任何对象之前,这将为向量提供足够的空间容纳两个对象。因此,它不需要重新分配,并且在main结尾之前不应该看到任何破坏。从技术上讲,如果编译器吸吮并生成不必要的副本,则可能会有更多的破坏。但是,从您目前所展示的情况来看,我认为t似乎没有这样做。

将语句打印到复制构造函数后,我们得到以下结果:

constructor A(0x7fff6e21e800)
constructor A(0x7fff6e21e7f8)
copy A(0x10e700910: From 0x7fff6e21e800)
1
copy A(0x10e700920: From 0x10e700910)
copy A(0x10e700928: From 0x7fff6e21e7f8)
destruct A(0x10e700910)
test
destruct A(0x10e700920)
destruct A(0x10e700928)
destruct A(0x7fff6e21e7f8)
destruct A(0x7fff6e21e800)
现在让我们看看代码:

int main()
{
   A o1,
     // constructor A(0x7fff6e21e800)
         o2;
     // constructor A(0x7fff6e21e7f8)
   vector <A > O;
   O.push_back(o1);
     // copy A(0x10e700910: From 0x7fff6e21e800)
   cout<<"1"<<endl;
     // 1

   O.push_back(o2);
    // copy A(0x10e700920: From 0x10e700910)    // O needs to expand.
                                                // So a new range is created and the old value
                                                // copied from the old range to the new range.

                                                // Now we push o2 into the vector
    // copy A(0x10e700928: From 0x7fff6e21e7f8)

                                                // Now the old range has to be destroyed.
    // destruct A(0x10e700910)


   cout<<"test"<<endl;
    // test


   return 0;
                 // Before we exit destroy the old vector (of two items)
    // destruct A(0x10e700920)
    // destruct A(0x10e700928)

                // Now destroy o2 then o1
    // destruct A(0x7fff6e21e7f8)
    // destruct A(0x7fff6e21e800)
}
intmain()
{
A o1,
//构造函数A(0x7fff6e21e800)
氧气;
//构造函数A(0x7fff6e21e7f8)
向量O;
O.推回(o1);
//复制A(0x10e700910:来自0x7fff6e21e800)

coutYou还需要执行复制构造函数。不理解为什么“O需要扩展。因此创建了一个新范围,并将旧值从旧范围复制到新范围。”第一次创建
O
时,它的容量可能为1。推送第一个元素后,它现在已满。但vector将自动展开,当它展开时,它必须将所有元素从旧数据区域复制到新数据区域。如果调用
O.reseve()
在开始推送元素之前,此额外副本将消失。
int main()
{
   A o1,
     // constructor A(0x7fff6e21e800)
         o2;
     // constructor A(0x7fff6e21e7f8)
   vector <A > O;
   O.push_back(o1);
     // copy A(0x10e700910: From 0x7fff6e21e800)
   cout<<"1"<<endl;
     // 1

   O.push_back(o2);
    // copy A(0x10e700920: From 0x10e700910)    // O needs to expand.
                                                // So a new range is created and the old value
                                                // copied from the old range to the new range.

                                                // Now we push o2 into the vector
    // copy A(0x10e700928: From 0x7fff6e21e7f8)

                                                // Now the old range has to be destroyed.
    // destruct A(0x10e700910)


   cout<<"test"<<endl;
    // test


   return 0;
                 // Before we exit destroy the old vector (of two items)
    // destruct A(0x10e700920)
    // destruct A(0x10e700928)

                // Now destroy o2 then o1
    // destruct A(0x7fff6e21e7f8)
    // destruct A(0x7fff6e21e800)
}