C++:STL:vector:remove:析构函数调用

Dad*_*dyM 2 c++ destructor vector std

代码如下:

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

struct A {
  A(int i = -1): i_(i) {
    wcout << "Constructor: i = " << i_ << endl;
  }
  A(A const &a) {
    wcout << "Copy constructor: i = " << i_ << " a.i = " << a.i_ << endl;
    *this = a;
  }
  ~A() { wcout << "Destructor: i = " << i_ << endl; }
  A &operator=(A const& a) {
    wcout << "Copy assignment operator: i = " << i_ << " a.i = " << a.i_ << endl;
    i_ = a.i_;
    return *this;
  }
  bool operator==(A const& rhs) { return i_ == rhs.i_; }
  int get() { return i_; }
private:
  int i_;
};

int wmain() {
  A a[] = {1, 2, 3, 2, 4, 5};
  vector<A> v(a, a + sizeof a/sizeof a[0]);
  wcout << "==== Just before remove ====" << endl;
 remove(v.begin(), v.end(), 2);
  wcout << "==== Just after remove ====" << endl;

  return 0;
}
Run Code Online (Sandbox Code Playgroud)

输出:

==== Just before remove ====
Constructor: i = 2
Destructor: i = 2
Constructor: i = 2
Destructor: i = 2
Constructor: i = 2
Destructor: i = 2
Copy assignment operator: i = 2 a.i = 3
Constructor: i = 2
Destructor: i = 2
Constructor: i = 2
Destructor: i = 2
Copy assignment operator: i = 3 a.i = 4
Constructor: i = 2
Destructor: i = 2
Copy assignment operator: i = 2 a.i = 5
==== Just after remove ====
Run Code Online (Sandbox Code Playgroud)

问题是:为什么在remove()运行时调用析构函数6次?我需要弄清楚这个烂摊子.

注意:请在回答之前在您的系统上执行此代码.注意:MSVCPP 11

NPE*_*NPE 7

问题是:为什么在remove()运行时调用析构函数6次?

总之,析构函数调用与2隐式转换为Aby有关remove().每次这种隐式转换的结果超出范围时,A都会调用析构函数.

之所以那些隐式转换是remove()需要的每一个元素进行比较a2.唯一的方法是通过调用A::operator==(const A&):

  bool operator==(A const& rhs) { ... }
Run Code Online (Sandbox Code Playgroud)

由于rhs是类型const A&,编译器:

  1. 调用A(int)将其转换2A;
  2. 电话operator==(const A&);
  3. 要求A::~A()摧毁临时的.

后者是你所看到的析构函数调用.

如果要添加以下比较运算符A,您将看到这些析构函数调用消失:

  bool operator==(int rhs) { return i_ == rhs; }
Run Code Online (Sandbox Code Playgroud)

或者,如果你这样打电话remove(),你会看到所有bar一个析构函数调用消失:

remove( v.begin(), v.end(), A(2) );
Run Code Online (Sandbox Code Playgroud)

最后,如果你做A::A(int) explicit,编译器不会让你打电话remove()2作为最后一个参数(你必须与调用它A(2)).

  • 解释部分是错误的.`remove`将2作为`int`并为每个相等检查构造一个临时值.`std :: remove`不应传递对象以进行比较. (2认同)