假设我有赋值运算符,我的拷贝构造函数是this = obj好吗?

时间:2017-04-21 01:04:51

标签: c++ copy-constructor assignment-operator

基本上,我的问题如下:假设我已经为一个类创建了一个赋值运算符,它是违反约定还是不赞成让我的拷贝构造函数只是这个= item?

让我们说我只使用以下数据创建模板化的类:

private:
    int       _size;
    ItemType* _array;

如果我的赋值运算符如下:

template<class ItemType>
void obj<ItemType>::operator = (const obj & copyThis){
    _size = copyThis.getSize(); 
    _array = new ItemType[_size];
    for (int i = 0; i < _size; i++){
        //assuming getItemAt is a function that returns whatever is in given location of object's _array
        _array[i] = copyThis.getItemAt(i);
    }
}

那么如果我的复制构造函数如下,是否会违反惯例/看不起/认为不正确?

template<class ItemType>
obj<ItemType>::obj(const obj & copyThis){
    this = copyThis;
}

1 个答案:

答案 0 :(得分:1)

在复制构造函数中调用operator=通常是安全的(只要operator=不尝试将复制构造函数用作其逻辑的一部分)。

但是,您的operator=实施错误。它会泄漏内存,不会处理分配给自身的this,也不会返回对this的引用。

请改为尝试:

template<class ItemType>
obj<ItemType>::obj(const obj & copyThis)
    : _size(0), _array(0)
{
    *this = copyThis;
}

template<class ItemType>
obj<ItemType>& obj<ItemType>::operator=(const obj<ItemType> &copyThis)
{
    if (this != &copyThis)
    {
        int newSize = copyThis.getSize(); 
        ItemType *newArray = new ItemType[newSize];

        // consider using std::copy() instead:
        //
        // std::copy(copyThis._array, copyThis._array + newSize, newArray);
        //
        for (int i = 0; i < newSize; ++i) {
            newArray[i] = copyThis.getItemAt(i);
        }

        delete[] _array;
        _array = newArray;
        _size = newSize; 
    }

    return *this;
}

话虽这么说,通常使用复制构造函数实现operator=通常更好,而不是相反:

template<class ItemType>
obj<ItemType>::obj(const obj & copyThis)
    : _size(copyThis.getSize()), _array(new ItemType[_size])
{
    for (int i = 0; i < _size; ++i){
        _array[i] = copyThis.getItemAt(i);
    }

    // or:
    // std::copy(copyThis._array, copyThis._array + _size, _array);
}

template<class ItemType>
obj<ItemType>& obj<ItemType>::operator=(const obj<ItemType> &copyThis)
{
    if (this != &copyThis)
    {
        obj<ItemType> tmp(copyThis); 
        std::swap(_array, tmp._array);
        std::swap(_size, tmp._size);
    }

    return *this;
}

如果添加swap方法,可以稍微清理一下:

template<class ItemType>
obj<ItemType>::obj(const obj & copyThis)
    : _size(copyThis.getSize()), _array(new ItemType[_size])
{
    for (int i = 0; i < _size; ++i){
        _array[i] = copyThis.getItemAt(i);
    }
}

template<class ItemType>
void obj<ItemType>::swap(obj<ItemType> &swapThis)
{
    std::swap(_array, swapThis._array);
    std::swap(_size, swapThis._size);
}

template<class ItemType>
obj<ItemType>& obj<ItemType>::operator=(const obj<ItemType> &copyThis)
{
    if (this != &copyThis) {
        obj<ItemType>(copyThis).swap(*this); 
    }

    return *this;
}

话虽这么说,如果用std::vector替换手动数组,那么根本不需要手动实现复制构造函数或复制赋值运算符,编译器生成的默认运算符将会足够(因为std::vector已经实现了复制语义)。