永恒赋值运算符调用循环C++模板类

Posted

技术标签:

【中文标题】永恒赋值运算符调用循环C++模板类【英文标题】:Eternal assignment operator call loop C++ template class 【发布时间】:2020-12-03 12:06:31 【问题描述】:

我有一个矩阵类,其中包含其成员函数的子集,

#ifndef _CMATRIX_CUH_
#define _CMATRIX_CUH_

#include <thrust/device_vector.h>
#include <assert.h>
template<class T>
class CMatrix

private:

    size_t n_rows, n_cols;
    
    T **data;

    __host__ __device__ void allocate_data();

    __host__ __device__ void deallocate_data();
    
public:

    __host__ __device__ CMatrix(const size_t n_rows);

    __host__ __device__ CMatrix(const size_t n_rows, const size_t n_cols);

    __host__ __device__ CMatrix(const CMatrix &other);

    __host__ __device__ ~CMatrix();

    __host__ __device__ CMatrix& operator=(const CMatrix &rhs);


/****************************************************************************************
*  Name     : CMatrix
*  Function : Class constructor, initializes parameters and variables
*  Method   : 
*  Author   : 
*  Modified :
*****************************************************************************************/
template <class T>
__host__ __device__ CMatrix<T>::CMatrix(
    const size_t n_rows                                         // In: Amount of matrix rows
    ) :
    n_rows(n_rows), n_cols(n_rows)

    allocate_data();


template <class T>
__host__ __device__ CMatrix<T>::CMatrix(
    const size_t n_rows,                                        // In: Amount of matrix rows
    const size_t n_cols                                         // In: New amount of matrix columns
    ) :
    n_rows(n_rows), n_cols(n_cols)

    allocate_data();


template <class T>
__host__ __device__ CMatrix<T>::CMatrix(
    const CMatrix<T> &other                                     // In: Matrix/vector to copy
    ) :
    n_rows(other.n_rows), n_cols(other.n_cols)

    allocate_data();
    for (size_t i = 0; i < n_rows; i++)
    
        for (size_t j = 0; j < n_cols; j++)
        
            data[i][j] = other.data[i][j];
        
    


/****************************************************************************************
*  Name     : ~CMatrix
*  Function : Class destructor
*  Method   : 
*  Author   : 
*  Modified :
*****************************************************************************************/
template <class T>
__host__ __device__ CMatrix<T>::~CMatrix()

    deallocate_data();


/****************************************************************************************
*  Name     : operator=
*  Function : 
*  Author   : 
*  Modified :
*****************************************************************************************/
template <class T>
__host__ __device__ CMatrix<T>& CMatrix<T>::operator=(
    const CMatrix<T> &rhs                                       // In: Right hand side matrix/vector to assign
    )

    if (this == &rhs)
    
        return *this;
    
    deallocate_data();

    return *this = CMatrix<T>(rhs);


/****************************************************************************************
    Private functions
****************************************************************************************/
/****************************************************************************************
*  Name     : allocate_data
*  Function : 
*  Author   : 
*  Modified :
*****************************************************************************************/
template <class T>
__host__ __device__ void CMatrix<T>::allocate_data()

    assert(n_rows > 0 && n_cols > 0);
    data = new T*[n_rows];
    for (size_t i = 0; i < n_rows; i++)
    
        data[i] = new T[n_cols];
    


/****************************************************************************************
*  Name     : deallocate_data
*  Function : 
*  Author   : 
*  Modified :
*****************************************************************************************/
template <class T>
__host__ __device__ void CMatrix<T>::deallocate_data()

    if (data == nullptr)
    
        return;
    

    for (size_t i = 0; i < n_rows; i++)
    
        delete[] data[i];
    
    delete[] data;
    data = nullptr;


#endif

其中,当我在 main() 函数中调用赋值运算符时

CMatrix<double> t1(2);
CMatrix<double> t2(3);
t1 = t2;

由于赋值运算符一遍又一遍地调用自己并且永远不会返回,堆栈最终会出现分段错误,为什么?经过长时间的调试,我不知道是什么原因造成的。这不是教科书的三法则吗?我正在使用 const 引用并从分配中返回引用。是的,我知道我可以使用 std:: 等,问题是在我所知道的情况下,这在 Cuda 中是不可能的。

【问题讨论】:

【参考方案1】:

赋值运算符 CMatrix::operator= 递归调用自身。

template <class T>
__host__ __device__ CMatrix<T>& CMatrix<T>::operator=(
    const CMatrix<T> &rhs                                       // In: Right hand side matrix/vector to assign
    )

    ...

    return *this = CMatrix<T>(rhs);  // calls operator=

【讨论】:

该死,我不经意间认为那行只调用了复制构造函数,但显然情况并非如此,因为“this”已经存在..

以上是关于永恒赋值运算符调用循环C++模板类的主要内容,如果未能解决你的问题,请参考以下文章

如何为从C++中的模板继承的类重载赋值运算符

带有模板类的赋值运算符 - 没有可接受的转换,C++

C++:在派生类构造函数中调用基类赋值运算符的错误形式?

Visual C++ 2010 / QT:为啥调用类的赋值运算符?

防止在 C++ 中调用基赋值运算符

C++ template技巧性基础知识总结