为什么这个拷贝构造函数是必需的

时间:2013-07-29 00:51:30

标签: c++ copy-constructor default-copy-constructor

#include <iostream>
#include <vector>

using namespace std;

class A {
  private:
    int number;
  public:
    A() {number = 0;}
    A(int nr) {number = nr;}
    //A(const A& rhand) {this->number = rhand.number;}
    int get_number() const {return this->number;}
    A& operator=(const A& rhand) {
      this->number = rhand.number;
      return (*this);
    }
};

class B {
  private:
    vector<A*>* content;
    vector<A*>::iterator currA;
    bool currA_valid;
  public:
    B() {
      content = new vector<A*>;
      currA = content->begin();
      currA_valid = false;
    }
    void push_A(A* nA) {content->push_back(nA); currA_valid = false;}
    void push_A(A nA) {content->push_back(&nA); currA_valid = false;}
    A get_A() {
      if(!currA_valid) {
        currA = content->begin();
        if(!content->empty()) {
          currA_valid = true;
        }
      }
      if(currA == content->end() || this->content->empty()) {
        currA = content->begin();
        return A();
      }
      else {
        A result(**currA);
        ++currA;
        return result;
      }
    }
};

int main()
{
  B container;

  A* a1 = new A(1);
  cout << a1->get_number() << endl;
  A a2(2);
  cout << a2.get_number() << endl;

  container.push_A(a1);
  container.push_A(a2);


  A tmp;
  while((tmp = container.get_A()).get_number() != 0)
    cout << "Inhalt tmp: " << tmp.get_number() << endl;

  return 0;
}

最近我遇到了一个问题,我变成了这个代码片段。

基本上,B类是A类对象的容器。

在实际代码中,A要大得多,并且类型A的相同对象可能在容器中出现多次,因此为了节省空间,B只存储指向A的指针。

B :: push函数将A类对象提供给容器。

指针和值A重载。

主函数末尾的while循环是我想要的(有点像流式算子与iostream对象一起使用)。

B中的迭代器“currA”跟踪函数调用B :: get_A()最后返回的元素,因此对该函数的连续调用将返回B ::内容中的所有A对象,直到结束为止到达。在这种情况下,内部迭代器被重置,并返回一个带有内部无效标志的对象A(在本例中为简单起见A :: number为0)。

此程序的输出可能如下所示:

1
2
Inhalt tmp: 1 //content of a1
Inhalt tmp: 4620996 //content of a2

主函数实例化两个对象A a1(1)和A * a2(2)。

测试A :: get_number()显示的两个内部值。两者都按预期工作。但是,在我们将它们都送入容器并从中再次检索它们之后,只有a1被正确显示。 a2的内容只显示了一些随机数。

起初我想,我用一些指针犯了一个错误,但它证明了问题是固定的,如果一个人声明并定义类A的复制构造函数如下:

A(const A& rhand) {this->number = rhand.number;}

据我所知,复制构造函数将由c ++编译器隐式定义,如果没有提供,并且建议实现它,当类具有指针作为成员以避免浅拷贝时。但在这种情况下,A只有一个int。

我还试图通过摆脱B :: get_A()并通过其他方式获取容器内容来简化代码。即使没有实现默认构造函数,问题也消失了。 所以这是我的问题:

1。)编译器定义的复制构造函数是否与我提供的复制构造函数类似? 和
2.)复制构造函数甚至与实际问题有什么关系?如何实现复制构造函数来解决问题?

2 个答案:

答案 0 :(得分:2)

void push_A(A nA) {content->push_back(&nA); currA_valid = false;}

在这里,您按值获取A个对象。该对象是函数的本地对象。当函数返回时,对象不再存在,因此向量将留下无效指针。

你的拷贝构造函数的实现与修复问题无关,这只是巧合。

答案 1 :(得分:0)

是,如果未提供复制构造函数,则编译器会对其进行编写。但是,如果您定义自己的分配运算符或析构函数,则应该定义自己的copy-ctor实现。

通常,如果编写其中一个构造(Copy-ctor,assigment operator和/或析构函数)的实现,则必须编写自己的其他构造实现。

这称为“The Rule Of Three”。