C ++ Copy构造函数不复制

时间:2016-01-10 10:49:55

标签: c++ copy-constructor

我正在尝试使用复制构造函数将一个对象初始化为其他对象。我很困惑,如果我注释掉复制构造函数,它初始化很好但是使用下面的代码却没有。

class TDateTime : public TData {
public:
  TDateTime() : TData(EDataStateInvalid) {}
  TDateTime(const tm& aTm){};
  TDateTime(int aTm_sec, int aTm_min, int aTm_hour,
  int aTm_mday, int aTm_mon, int aTm_year, int aTm_wday,int aTm_isdst){
      value.tm_sec=aTm_sec;
      value.tm_min=aTm_min;
      value.tm_hour=aTm_hour;
      value.tm_mday=aTm_mday;
      value.tm_mon=aTm_mon;
      value.tm_year=aTm_year;
      value.tm_wday=aTm_wday;
      value.tm_isdst=aTm_isdst; 
  };
  virtual ~TDateTime() {cout<<"Destroying TDateTime ";};

  //! Copy constructor
  TDateTime(const TDateTime& aInstance){};
  //! Copies an instance
  virtual const TDateTime& operator=(const TDateTime& aInstance){return   *this;};
  private:
  tm value;
};



main.cpp
tm=createDateTime(x);
TDateTime     aDateTimeFrom(tm.tm_sec,tm.tm_min,tm.tm_hour,tm.tm_mday,tm.tm_mon,tm.tm_year,tm. tm_wday,0);  
TDateTime aDateTimeTo(aDateTimeFrom);

如果我注释掉复制构造函数,它就可以复制。如果我删除{}然后编译器抱怨未定义的符号。

你能说出这里有什么问题吗? 根据关于空副本构造函数的答案什么也没做,我评论出来并且复制是完美的但我有另一个问题。如果我做

TDateTime aDateTime;
aDateTime=aDateTimeFrom;

aDateTime具有所有垃圾值。关于这个的任何指示?

3 个答案:

答案 0 :(得分:2)

  //! Copy constructor
  TDateTime(const TDateTime& aInstance){};

您的复制构造函数不执行任何操作。用户编写的拷贝构造函数没有任何魔力;如果你不让他们做任何事情,那么他们就什么都不做。

更确切地说,创建了一个新的实例 ,但其成员未初始化或默认初始化。

虽然我们正在努力......

//! Copies an instance
  virtual const TDateTime& operator=(const TDateTime& aInstance){return   *this;};

这里的问题相同。您的副本分配操作符不执行任何操作。

按照惯例,它也不应该返回const引用而是返回非const引用。

值得一提的是,你的直觉似乎是正确的,因为你的目标确实应该是创建不需要任何自写复制构造函数或复制赋值运算符的类,因为所有成员都知道如何正确复制或复制自己(例如std::stringstd::vectorstd::shared_ptr)。但在这种情况下,不是用空实现定义成员函数,而是在代码中根本不要声明它们,这样编译器就可以自动处理所有内容。

最后,另外一件事:对C ++类来说,一个好的经验法则是它们要么具有虚函数并禁用复制(有时称为&#34;身份类&#34;)< em>或没有虚函数并允许复制(有时称为&#34;值类&#34;)。像虚拟赋值运算符这样的东西通常表示过于复杂,难以使用且容易出错的类设计。

答案 1 :(得分:1)

编译器生成一个复制构造函数,如果用户尚未声明复制构造函数,则执行成员复制。如果用户确实声明了一个复制构造函数,那么复制构造函数会执行用户告诉它的内容,在您的情况下 - 完全没有。

TDateTime(const TDateTime& aInstance){ /* empty body*/};

答案 2 :(得分:1)

定义一个不做任何事情的复制构造函数。

在你的情况下,你真的不需要复制构造函数和/或复制赋值运算符,编译器生成的版本就足够了(确保/重新检查 tm 类可以是明智的处理复制)。

有一个rule of three,它表明如果定义析构函数,则需要复制构造函数和复制赋值运算符。但这只是一个经验法则,而不是一个实际需要。在您的情况下,不涉及内存管理,您只使用析构函数进行日志记录。

所以根本不要声明一个拷贝构造函数(顺便说一下你的assign运算符有相同的缺陷 - 它不会复制任何东西)并让编译器完成工作。