【问题标题】:C++ Template Copy Constructor Deep CopyC++ 模板复制构造函数深度复制
【发布时间】:2012-04-05 02:49:26
【问题描述】:

为了方便起见,我正在编写一个通用 Array 类并重载运算符。我已经让我的 Array 对象来保存其他 Array 对象,但是我在覆盖 * 运算符时遇到了麻烦。我需要复制左边的对象,所以我的 operator* 代码是这样的:

Array<T>& operator*(const double scalar) {
    return Array<T>(*this) *= scalar;
}

(operator*= 已被重载并且可以工作)。

我重写了复制构造函数如下:

更新:新的复制构造函数:

Array<T> (const Array<T>& copyfrom) {
    size_=copyfrom.size();
    data=new T[size_];
    copy(&copyfrom.data[0], &copyfrom.data[size_], data);
}

我的想法是,如果数组不是泛型的,但总是用原语填充,那么这段代码就可以工作。但我认为这里发生了一些事情,因为我使用的模板会导致我不期望的行为。新“深复制”数组中的数据数组就像是“copyfrom”数据数组的浅指针副本。

如何使用模板使这个复制构造函数同时适用于基元和对象?或者,更好的是,有没有办法重载 operator* 而不必担心复制构造函数?谢谢。

编辑:这是operator*= 的代码。但是,我仍然认为我的问题在于我使用了复制构造函数。

Array<T>& operator*=(const double scalar) {
    for (int i=0; i<size_; i++)
        data[i]*=scalar;
    return *this;
}

编辑:我意识到我遇到了问题,因为我忽略了数组数组中内部数组的size。现在事情更可靠了。每个人都非常乐于助人,我想我正在努力完成这项工作。我的operator=(我没有超载;很好,迈克尔)现在如下。它按预期运行,但我的程序中开始出现malloc 错误,我正在探索原因。这里的内存管理有什么问题吗?

Array<T>& operator=(const Array<T>& a) {
    if (this==&a)
        return *this;
    delete [] data;

    size_=a.size();
    data=new T(size_);
    copy(&a.data[0], &a.data[a.size()], data);

    return *this;
}

编辑:我修复了malloc 错误!我的方法现在都按预期工作。内存问题来了,因为我有这个方法头:

template <typename T>
static Array<T> matrixSolve (Array<Array<T> > m);

我正在按值获取一组数组。各种问题。通过引用获取数组,一切都解决了。谢谢大家的帮助!

【问题讨论】:

  • @MichaelAnderson operator* 的代码不应返回 thisArray&lt;T&gt;(*this) 的调用调用了我已经确认的复制构造函数。此外,如果我将operator* 设为 const,则在使用 operator*= 时不会出现编译错误,因此我不能变异 this
  • 你是对的 - 我会删除那些 cmets。
  • 你能告诉我们Array&lt;T&gt;::operator=吗?当您使用data[i]=copyfrom.data[i] 时,您正在为数据调用operator=。如果未定义,您将获得默认值。所以如果你嵌套 Arrays 并且 Array 没有 = 那么坏事就会发生。
  • 您是否有理由不使用std::vectorstd::array 作为data 成员?然后,您可能会让默认的复制构造函数和赋值运算符做正确的事情。
  • @MichaelAnderson 我想你成功了;我正在嵌套数组并在 Array&lt;T&gt; 对象上调用 operator=。这可能是个问题。我要超载operator=,我会回复你。

标签: c++ arrays templates containers


【解决方案1】:

你会希望你的 operator* 成员函数看起来像这样:

Array<T> operator*(const double scalar) const {
    Array<T> result(*this);
    result *= scalar;
    return result;
}

如果您返回 Array&lt;T&gt; &amp;,那么您将返回对将被销毁的临时对象的引用,从而导致未定义的行为。

【讨论】:

  • 你可能也想让operator* const。
  • @MichaelAnderson: true -- 改变了
  • 将这三行合二为一并没有什么不好,就像在 OP 的原始代码中一样;实际上,我认为它更具可读性,因为您不会引入声明临时变量名的噪音,并且可以立即看出您实际上是在执行“*this *= scalar with a backup”。只是引用返回和缺少的const 是错误的。
  • @leftaroundabout:我不认为很多人会同意。使用(lhs *= rhs) 作为右值等于lhs 不是那么可读。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-12-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-12-08
相关资源
最近更新 更多