在std :: vector :: clear之后关于vector中的构造/破坏的困惑

MKR*_*sha 6 c++

#include <iostream>
#include <vector>

class A
{
public:
    A() { std::cout << "constructor" << std::endl; }

    ~A() { std::cout << "destructor" << std::endl; }
};

int main()
{
    std::vector<A> myvec;
    myvec.push_back(A());
    myvec.push_back(A());
    myvec.clear();
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

输出:

constructor
destructor
constructor
destructor
destructor
destructor
destructor
Run Code Online (Sandbox Code Playgroud)

这里有五个对析构函数的调用.前两个是由于临时传递给push_back.还有其他三个电话,但我预计会有两个额外的电话.

myvec.clear()将只清除两个内容,因此析构函数A应该只调用两次(而不是三次).为什么有一个额外的时间析构函数被调用?

但是,如果我只将一个元素推送到向量而不是两个,那么输出就像我预期的那样.

edm*_*dmz 8

调用std::vector::clear在这种情况下并不重要,因为当myvec超出范围时,其内容将被销毁.


我们考虑一下

class A
{
public:
    A()  { std::cout << "constructor" << std::endl; }
    ~A() { std::cout << "destructor" << std::endl; }
    A (const A &) { std::cout << "A(A&)\n"; }

};

int main()
{
    std::vector<A> myvec;

    std::cout << "First\n";
    myvec.push_back(A());

    std::cout << "Second\n";
    myvec.push_back(A());

    std::cout << '\n'; // to separate the final destruction

    myvec.clear();
}
Run Code Online (Sandbox Code Playgroud)

哪个输出

First
constructor <-- First A _temporary_ object created when pushing_back
A(A&)       <-- vector makes a *copy* of the temporary
destructor  <-- Temporary A is destroyed
Second     
constructor <-- Second A _temporary_ object created when pushing_back
A(A&)       <-- Reallocation happens: vector can't copy because it ran out of space
A(A&)       <-- Copy of the second temporary
destructor  <-- Destroy of the temporary
destructor  <-- Destroy of the first element

destructor
destructor
Run Code Online (Sandbox Code Playgroud)

如果你std::vector::reserve有一些空间,你可以摆脱重新分配所产生的副本

std::vector<A> myvec;
myvec.reserve(8);
Run Code Online (Sandbox Code Playgroud)

这证实了什么

First
constructor
A(A&) 
destructor
Second
constructor
A(A&) 
destructor
Run Code Online (Sandbox Code Playgroud)

push_back 仍在制作参数的副本:这可以通过使您的类可移动来进一步优化.

A(A&&) noexcept = default;
A& operator=(A&&) noexcept = default;

First
constructor
destructor
Second
constructor
destructor
Run Code Online (Sandbox Code Playgroud)


Sho*_*hoe 5

这很可能是由于在第一次和第二次之间发生的重新分配push_back.如果你reserve提前一些空间,那么解除分配将2在两个push_backs之后,如你所料.


Jab*_*cky 5

试试这个稍微修改过的程序版本.现在有一个复制构造函数和一个可选项reserve(请参阅程序中的注释).发生的事情会更清楚.

#include <iostream>
#include <vector>

using namespace std;


class A
{
  public:
  A()            { cout << " constructor" << endl; }
  A(const A & a) { cout << " copy constructor" << endl; }
  ~A()           { cout << " destructor" << endl; }
};



int main()
{
  vector<A> myvec;

  // myvec.reserve(100);                   // <<< remove comment to see the difference

  cout << "pushback 1" << endl;
  myvec.push_back(A());

  cout << "pushback 2"  << endl;
  myvec.push_back(A());

  cout << "pushback 3"  << endl;
  myvec.push_back(A());

  cout << "clear"  << endl;
  myvec.clear();
  cout << "end clear" << endl;
  return 0;
}
Run Code Online (Sandbox Code Playgroud)