在C ++中返回带有指针成员变量的对象

时间:2014-03-25 08:12:20

标签: c++

所以我有一个upDate对象,它有一个指针成员变量,只指向一个默认为1959年5月11日的数组:

upDate::upDate()
{   dptr = new int[3];
    dptr[0] = 5;
    dptr[1] = 11;
    dptr[2] = 1959;
}

现在在我的主要内容我应该覆盖+运算符。

upDate D1(5,9,1994);
upDate D2 = D1+1;//supposed to add 1 more day to the upDate.

但是当我输出D2时,它并没有我5/10/1994。它给了我一个非常大的负数:-572662307 / -572662307 / -572662307.。

这是我的算子+方法:

upDate upDate::operator+(int integer){
    upDate temp;
    int m = dptr[0];
    //cout << m << endl;
    int d = dptr[1];
    int y = dptr[2];
    int julian = convertToJulian(y, m, d);
    julian += integer;
    //cout << julian << endl;
    temp.convertToGregorian(julian);
    //cout << temp.getMonth() << " " << temp.getDay() << " " << temp.getYear() << endl;
    return temp;
}

该方法中的所有cout都只是我测试它是否正确,它们是正确的。所以,我不认为其中任何一个是不正确的。但是,当我返回临时状态时,我认为在将温度恢复为D2的过程中会丢失一些东西。也许它是一个指针问题?我不太确定。

编辑:这是我的运营商=:

upDate upDate::operator=(upDate copy) {
for(int i = 0; i<3; i++)
    copy.dptr[i] = dptr[i];
return copy;
}

和我的析构函数:

upDate::~upDate()
{
    delete []dptr;
}

我想我从来没有制作过复制构造函数......但我对如何制作它很困惑?

3 个答案:

答案 0 :(得分:1)

  

也许这是一个指针问题?

可能。在您的更新中,您说“我想我从未创建过复制构造函数”,这意味着该类会破坏Rule of Three并具有无效的复制语义。当它被复制时(就像从你发布的函数返回时那样),两个副本都包含一个指向同一个数组的指针;据推测,两者都有一个析构函数,删除数组,让另一个对象的指针悬空。

  

我想我从未做过复制构造函数......但我对如何制作它感到困惑?

制作它的最佳方法不是。停止使用new并手动处理指针,并从正确的可复制对象构建类;在这种情况下,将dptr替换为数组或三个命名变量。 (如果你需要一个动态大小的数组,你不在这里,那么std::vector将是理想的。)

我可能会通过仅存储Julian日来进一步简化它,并且只在必要时转换为Gregorian以进行人类可读的演示。

如果你真的觉得需要通过steam管理内存,那么你需要一个析构函数

~upDate() {delete [] dptr;}

复制构造函数

upDate(upDate const & other) : dptr(new int[3]) {
    std::copy(other.dptr, other.dptr+3, dptr);
}

和复制赋值运算符。它应该修改它所调用的对象,而不是它的参数(当然也不是你的参数的本地副本),并且通常应该返回对指定对象的引用,而不是它的副本。

upDate & operator=(upDate const & other) {
    std::copy(other.dptr, other.dptr+3, dptr);
    return *this;
}

在C ++ 11中,为了提高效率,您可能还需要考虑移动语义。

upDate(upDate && other) : dptr(other.dptr) {
    other.dptr = nullptr;
}

upDate & operator=(upDate && other) {
    if (this != &other) {   // Careful: self-assignment can be tricky
        dptr = other.dptr;
        other.dptr = nullptr;
    }
}

免责声明:此代码是在没有编译器和测试框架的帮助下编写的,因此可能包含错误。不经测试就不要使用它。

tl; dr 内存管理很难。除非你真的需要,否则不要这样做。你不需要在这里。

答案 1 :(得分:0)

您的operator=功能可以倒退。

//This version tries to make a=b work as though it were b=a
upDate upDate::operator=(upDate copy) {
  for(int i = 0; i<3; i++)
    copy.dptr[i] = dptr[i];
  return copy;
}

也就是说,通过examples I have seen判断operator=应该将参数的值复制到当前对象中,然后将其从当前对象复制到参数。

//Corrected version (judging by linked article.)
upDate & upDate::operator=(upDate copy) {
  for(int i = 0; i<3; i++)
    dptr[i] = copy.dptr[i];
  return *this;
}

答案 2 :(得分:0)

  

我想我从来没有制作过复制构造函数

即可。注意这一行upDate D2 = D1+1;,它会调用复制构造函数而不是operator =,因为你没有指定一个,它会调用编译器生成的复制构造函数来执行成员复制,所以数据成员{{ 1}},他们共享相同的地址。销毁D2.dptr = temp.dptr后,temp指向无效的地址,因此它会为您提供垃圾值。