OpenCV源码阅读(2)---matx.h---函数的内联实现

来源:互联网 发布:手机端淘宝店铺装修 编辑:程序博客网 时间:2024/04/30 12:18

外部矩阵计算函数

namespace internal{template<typename _Tp, int m> struct Matx_DetOp{    double operator ()(const Matx<_Tp, m, m>& a) const    {        Matx<_Tp, m, m> temp = a;        double p = LU(temp.val, m*sizeof(_Tp), m, 0, 0, 0);        if( p == 0 )            return p;        for( int i = 0; i < m; i++ )            p *= temp(i, i);        return 1./p;    }};template<typename _Tp> struct Matx_DetOp<_Tp, 1>{    double operator ()(const Matx<_Tp, 1, 1>& a) const    {        return a(0,0);    }};template<typename _Tp> struct Matx_DetOp<_Tp, 2>{    double operator ()(const Matx<_Tp, 2, 2>& a) const    {        return a(0,0)*a(1,1) - a(0,1)*a(1,0);    }};template<typename _Tp> struct Matx_DetOp<_Tp, 3>{    double operator ()(const Matx<_Tp, 3, 3>& a) const    {        return a(0,0)*(a(1,1)*a(2,2) - a(2,1)*a(1,2)) -            a(0,1)*(a(1,0)*a(2,2) - a(2,0)*a(1,2)) +            a(0,2)*(a(1,0)*a(2,1) - a(2,0)*a(1,1));    }};

上面的函数定义了矩阵行列式计算的计算。高于3阶的矩阵使用LU分解算法,低于3阶矩阵对Matx_DetOp进行了重载,使用直接计算行列式的方式来计算。这里使用的是在结构体里定义计算的方式。这样做的目的是什么呢?需要继续看类是如何调用这些操作的

template<typename _Tp> Vec<_Tp, 2> inline conjugate(const Vec<_Tp, 2>& v){    return Vec<_Tp, 2>(v[0], -v[1]);}template<typename _Tp> Vec<_Tp, 4> inline conjugate(const Vec<_Tp, 4>& v){    return Vec<_Tp, 4>(v[0], -v[1], -v[2], -v[3]);}

这里使用内联的方式来实现向量共轭的计算。。。但是向量类中并没有定义共轭函数conjugate,只有一个conj。这是错误吗?

矩阵构造函数与基本运算

template<typename _Tp, int m, int n> inlineMatx<_Tp, m, n>::Matx(){    for(int i = 0; i < channels; i++) val[i] = _Tp(0);}template<typename _Tp, int m, int n> inlineMatx<_Tp, m, n>::Matx(_Tp v0){    val[0] = v0;    for(int i = 1; i < channels; i++) val[i] = _Tp(0);}template<typename _Tp, int m, int n> inlineMatx<_Tp, m, n>::Matx(_Tp v0, _Tp v1){    CV_StaticAssert(channels >= 2, "Matx should have at least 2 elaments.");    val[0] = v0; val[1] = v1;    for(int i = 2; i < channels; i++) val[i] = _Tp(0);}template<typename _Tp, int m, int n> inlineMatx<_Tp, m, n>::Matx(_Tp v0, _Tp v1, _Tp v2){    CV_StaticAssert(channels >= 3, "Matx should have at least 3 elaments.");    val[0] = v0; val[1] = v1; val[2] = v2;    for(int i = 3; i < channels; i++) val[i] = _Tp(0);}template<typename _Tp, int m, int n> inlineMatx<_Tp, m, n>::Matx(_Tp v0, _Tp v1, _Tp v2, _Tp v3){    CV_StaticAssert(channels >= 4, "Matx should have at least 4 elaments.");    val[0] = v0; val[1] = v1; val[2] = v2; val[3] = v3;    for(int i = 4; i < channels; i++) val[i] = _Tp(0);}template<typename _Tp, int m, int n> inlineMatx<_Tp, m, n>::Matx(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4){    CV_StaticAssert(channels >= 5, "Matx should have at least 5 elaments.");    val[0] = v0; val[1] = v1; val[2] = v2; val[3] = v3; val[4] = v4;    for(int i = 5; i < channels; i++) val[i] = _Tp(0);}template<typename _Tp, int m, int n> inlineMatx<_Tp, m, n>::Matx(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5){    CV_StaticAssert(channels >= 6, "Matx should have at least 6 elaments.");    val[0] = v0; val[1] = v1; val[2] = v2; val[3] = v3;    val[4] = v4; val[5] = v5;    for(int i = 6; i < channels; i++) val[i] = _Tp(0);}template<typename _Tp, int m, int n> inlineMatx<_Tp, m, n>::Matx(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5, _Tp v6){    CV_StaticAssert(channels >= 7, "Matx should have at least 7 elaments.");    val[0] = v0; val[1] = v1; val[2] = v2; val[3] = v3;    val[4] = v4; val[5] = v5; val[6] = v6;    for(int i = 7; i < channels; i++) val[i] = _Tp(0);}template<typename _Tp, int m, int n> inlineMatx<_Tp, m, n>::Matx(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5, _Tp v6, _Tp v7){    CV_StaticAssert(channels >= 8, "Matx should have at least 8 elaments.");    val[0] = v0; val[1] = v1; val[2] = v2; val[3] = v3;    val[4] = v4; val[5] = v5; val[6] = v6; val[7] = v7;    for(int i = 8; i < channels; i++) val[i] = _Tp(0);}template<typename _Tp, int m, int n> inlineMatx<_Tp, m, n>::Matx(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5, _Tp v6, _Tp v7, _Tp v8){    CV_StaticAssert(channels >= 9, "Matx should have at least 9 elaments.");    val[0] = v0; val[1] = v1; val[2] = v2; val[3] = v3;    val[4] = v4; val[5] = v5; val[6] = v6; val[7] = v7;    val[8] = v8;    for(int i = 9; i < channels; i++) val[i] = _Tp(0);}template<typename _Tp, int m, int n> inlineMatx<_Tp, m, n>::Matx(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5, _Tp v6, _Tp v7, _Tp v8, _Tp v9){    CV_StaticAssert(channels >= 10, "Matx should have at least 10 elaments.");    val[0] = v0; val[1] = v1; val[2] = v2; val[3] = v3;    val[4] = v4; val[5] = v5; val[6] = v6; val[7] = v7;    val[8] = v8; val[9] = v9;    for(int i = 10; i < channels; i++) val[i] = _Tp(0);}template<typename _Tp, int m, int n> inlineMatx<_Tp,m,n>::Matx(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5, _Tp v6, _Tp v7, _Tp v8, _Tp v9, _Tp v10, _Tp v11){    CV_StaticAssert(channels == 12, "Matx should have at least 12 elaments.");    val[0] = v0; val[1] = v1; val[2] = v2; val[3] = v3;    val[4] = v4; val[5] = v5; val[6] = v6; val[7] = v7;    val[8] = v8; val[9] = v9; val[10] = v10; val[11] = v11;}template<typename _Tp, int m, int n> inlineMatx<_Tp,m,n>::Matx(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5, _Tp v6, _Tp v7, _Tp v8, _Tp v9, _Tp v10, _Tp v11, _Tp v12, _Tp v13, _Tp v14, _Tp v15){    CV_StaticAssert(channels == 16, "Matx should have at least 16 elaments.");    val[0] = v0; val[1] = v1; val[2] = v2; val[3] = v3;    val[4] = v4; val[5] = v5; val[6] = v6; val[7] = v7;    val[8] = v8; val[9] = v9; val[10] = v10; val[11] = v11;    val[12] = v12; val[13] = v13; val[14] = v14; val[15] = v15;}template<typename _Tp, int m, int n> inlineMatx<_Tp, m, n>::Matx(const _Tp* values){    for( int i = 0; i < channels; i++ ) val[i] = values[i];}template<typename _Tp, int m, int n> inlineMatx<_Tp, m, n> Matx<_Tp, m, n>::all(_Tp alpha){    Matx<_Tp, m, n> M;    for( int i = 0; i < m*n; i++ ) M.val[i] = alpha;    return M;}template<typename _Tp, int m, int n> inlineMatx<_Tp,m,n> Matx<_Tp,m,n>::zeros(){    return all(0);}template<typename _Tp, int m, int n> inlineMatx<_Tp,m,n> Matx<_Tp,m,n>::ones(){    return all(1);}template<typename _Tp, int m, int n> inlineMatx<_Tp,m,n> Matx<_Tp,m,n>::eye(){    Matx<_Tp,m,n> M;    for(int i = 0; i < shortdim; i++)        M(i,i) = 1;    return M;}template<typename _Tp, int m, int n> inline_Tp Matx<_Tp, m, n>::dot(const Matx<_Tp, m, n>& M) const{    _Tp s = 0;    for( int i = 0; i < channels; i++ ) s += val[i]*M.val[i];    return s;}template<typename _Tp, int m, int n> inlinedouble Matx<_Tp, m, n>::ddot(const Matx<_Tp, m, n>& M) const{    double s = 0;    for( int i = 0; i < channels; i++ ) s += (double)val[i]*M.val[i];    return s;}/** @cond IGNORED */template<typename _Tp, int m, int n> inlineMatx<_Tp,m,n> Matx<_Tp,m,n>::diag(const typename Matx<_Tp,m,n>::diag_type& d){    Matx<_Tp,m,n> M;    for(int i = 0; i < shortdim; i++)        M(i,i) = d(i, 0);    return M;}

这一大段使用内联函数实现了矩阵的定义和加,减,点乘,点除等基础操作,使用内联的作用是提高效率。可以看出,对于低阶矩阵,opencv的做法十分粗暴,直接访问数组数据成员,然后赋值。不过在赋值和构造之前使用了CV_staticAssert来验证是否会溢出,这是c++的断言功能,不知opencv是如何重新利用的。

template<typename _Tp, int m, int n> template<typename T2>inline Matx<_Tp, m, n>::operator Matx<T2, m, n>() const{    Matx<T2, m, n> M;    for( int i = 0; i < m*n; i++ ) M.val[i] = saturate_cast<T2>(val[i]);    return M;}

这个函数作用是操作符的重载,重载了操作符(),作用是复制一个矩阵。其中使用了saturate_cast<T2> 模板函数,作用是防止内存溢出,但是这个函数不在这个文件中,我猜在bufferpool.h里。

template<typename _Tp, int m, int n> template<int m1, int n1> inlineMatx<_Tp, m1, n1> Matx<_Tp, m, n>::reshape() const{    CV_StaticAssert(m1*n1 == m*n, "Input and destnarion matrices must have the same number of elements");    return (const Matx<_Tp, m1, n1>&)*this;}

reshape函数,作用是将具有相同元素数目的矩阵转换形式。例如9*1–>3*3

template<typename _Tp, int m, int n>template<int m1, int n1> inlineMatx<_Tp, m1, n1> Matx<_Tp, m, n>::get_minor(int i, int j) const{    CV_DbgAssert(0 <= i && i+m1 <= m && 0 <= j && j+n1 <= n);    Matx<_Tp, m1, n1> s;    for( int di = 0; di < m1; di++ )        for( int dj = 0; dj < n1; dj++ )            s(di, dj) = (*this)(i+di, j+dj);    return s;}

由矩阵的第i行,第j列开始,抽取一个较小的矩阵。

这里使用了this指针的方式,把this指针式只想类所定义的对象的指针,也就是说,如果定义Matx m(3,3), m.get_minor(2,2) 那么this指针是只想m的,所以可以用(*this)的方式表示提取m中的数据。

template<typename _Tp, int m, int n> inlineMatx<_Tp, 1, n> Matx<_Tp, m, n>::row(int i) const{    CV_DbgAssert((unsigned)i < (unsigned)m);    return Matx<_Tp, 1, n>(&val[i*n]);}template<typename _Tp, int m, int n> inlineMatx<_Tp, m, 1> Matx<_Tp, m, n>::col(int j) const{    CV_DbgAssert((unsigned)j < (unsigned)n);    Matx<_Tp, m, 1> v;    for( int i = 0; i < m; i++ )        v.val[i] = val[i*n + j];    return v;}

提取第i行第j列的函数,对于提取行,可以直接使用val[i*n]的方式,这种方式表达的是,因为val[m*n] 是一个m*n的数组,是一个一维数组。如果是一个行矩阵的话,可以用这个数组的首地址进行初始化,将母矩阵该行首地址作为子矩阵数据首地址即可。并且这些函数都是const类型,保护了原本矩阵的数据。

template<typename _Tp, int m, int n> inlinetypename Matx<_Tp, m, n>::diag_type Matx<_Tp, m, n>::diag() const{    diag_type d;    for( int i = 0; i < shortdim; i++ )        d.val[i] = val[i*n + i];    return d;}

提取对角元素。

template<typename _Tp, int m, int n> inlineconst _Tp& Matx<_Tp, m, n>::operator()(int i, int j) const{    CV_DbgAssert( (unsigned)i < (unsigned)m && (unsigned)j < (unsigned)n );    return this->val[i*n + j];}template<typename _Tp, int m, int n> inline_Tp& Matx<_Tp, m, n>::operator ()(int i, int j){    CV_DbgAssert( (unsigned)i < (unsigned)m && (unsigned)j < (unsigned)n );    return val[i*n + j];}template<typename _Tp, int m, int n> inlineconst _Tp& Matx<_Tp, m, n>::operator ()(int i) const{    CV_StaticAssert(m == 1 || n == 1, "Single index indexation requires matrix to be a column or a row");    CV_DbgAssert( (unsigned)i < (unsigned)(m+n-1) );    return val[i];}template<typename _Tp, int m, int n> inline_Tp& Matx<_Tp, m, n>::operator ()(int i){    CV_StaticAssert(m == 1 || n == 1, "Single index indexation requires matrix to be a column or a row");    CV_DbgAssert( (unsigned)i < (unsigned)(m+n-1) );    return val[i];}

重载操作符(),用于访问矩阵内元素,操作符重载是c++中非常重要的操作。这里使用了_Tp & Matx<_Tp,m,n>::operator ()(int i,int j){} 是把操作符重载为成员函数的做法。其中,i是第一个操作数,j是第二个操作数。

template<typename _Tp, int m, int n> inlineMatx<_Tp,m,n>::Matx(const Matx<_Tp, m, n>& a, const Matx<_Tp, m, n>& b, Matx_AddOp){    for( int i = 0; i < channels; i++ )        val[i] = saturate_cast<_Tp>(a.val[i] + b.val[i]);}template<typename _Tp, int m, int n> inlineMatx<_Tp,m,n>::Matx(const Matx<_Tp, m, n>& a, const Matx<_Tp, m, n>& b, Matx_SubOp){    for( int i = 0; i < channels; i++ )        val[i] = saturate_cast<_Tp>(a.val[i] - b.val[i]);}template<typename _Tp, int m, int n> template<typename _T2> inlineMatx<_Tp,m,n>::Matx(const Matx<_Tp, m, n>& a, _T2 alpha, Matx_ScaleOp){    for( int i = 0; i < channels; i++ )        val[i] = saturate_cast<_Tp>(a.val[i] * alpha);}template<typename _Tp, int m, int n> inlineMatx<_Tp,m,n>::Matx(const Matx<_Tp, m, n>& a, const Matx<_Tp, m, n>& b, Matx_MulOp){    for( int i = 0; i < channels; i++ )        val[i] = saturate_cast<_Tp>(a.val[i] * b.val[i]);}template<typename _Tp, int m, int n> inlineMatx<_Tp,m,n>::Matx(const Matx<_Tp, m, n>& a, const Matx<_Tp, m, n>& b, Matx_DivOp){    for( int i = 0; i < channels; i++ )        val[i] = saturate_cast<_Tp>(a.val[i] / b.val[i]);}template<typename _Tp, int m, int n> template<int l> inlineMatx<_Tp,m,n>::Matx(const Matx<_Tp, m, l>& a, const Matx<_Tp, l, n>& b, Matx_MatMulOp){    for( int i = 0; i < m; i++ )        for( int j = 0; j < n; j++ )        {            _Tp s = 0;            for( int k = 0; k < l; k++ )                s += a(i, k) * b(k, j);            val[i*n + j] = s;        }}template<typename _Tp, int m, int n> inlineMatx<_Tp,m,n>::Matx(const Matx<_Tp, n, m>& a, Matx_TOp){    for( int i = 0; i < m; i++ )        for( int j = 0; j < n; j++ )            val[i*n + j] = a(j, i);}

特殊的矩阵构造函数
定义了矩阵的基本操作,包括加减乘除缩放,这些操作作为矩阵的构造函数,可以生成一个新的矩阵,也就是支持由两个矩阵生成新的矩阵。

template<typename _Tp, int m, int n> inlineMatx<_Tp, m, n> Matx<_Tp, m, n>::mul(const Matx<_Tp, m, n>& a) const{    return Matx<_Tp, m, n>(*this, a, Matx_MulOp());}template<typename _Tp, int m, int n> inlineMatx<_Tp, m, n> Matx<_Tp, m, n>::div(const Matx<_Tp, m, n>& a) const{    return Matx<_Tp, m, n>(*this, a, Matx_DivOp());}template<typename _Tp, int m, int n> inlineMatx<_Tp, n, m> Matx<_Tp, m, n>::t() const{    return Matx<_Tp, n, m>(*this, Matx_TOp());    template<typename _Tp, int m, int n> inline}Vec<_Tp, n> Matx<_Tp, m, n>::solve(const Vec<_Tp, m>& rhs, int method) const{    Matx<_Tp, n, 1> x = solve((const Matx<_Tp, m, 1>&)(rhs), method);    return (Vec<_Tp, n>&)(x);}template<typename _Tp, int m> static inlinedouble determinant(const Matx<_Tp, m, m>& a){    return internal::Matx_DetOp<_Tp, m>()(a);}template<typename _Tp, int m, int n> static inlinedouble trace(const Matx<_Tp, m, n>& a){    _Tp s = 0;    for( int i = 0; i < std::min(m, n); i++ )        s += a(i,i);    return s;}template<typename _Tp, int m, int n> static inlinedouble norm(const Matx<_Tp, m, n>& M){    return std::sqrt(normL2Sqr<_Tp, double>(M.val, m*n));}template<typename _Tp, int m, int n> static inlinedouble norm(const Matx<_Tp, m, n>& M, int normType){    return normType == NORM_INF ? (double)normInf<_Tp, typename DataType<_Tp>::work_type>(M.val, m*n) :        normType == NORM_L1 ? (double)normL1<_Tp, typename DataType<_Tp>::work_type>(M.val, m*n) :        std::sqrt((double)normL2Sqr<_Tp, typename DataType<_Tp>::work_type>(M.val, m*n));}

实现矩阵本身的乘,除,转置操作。如果已经有了一个两个矩阵,可以以成员函数的方式来生成结果。例如

Matx a(####);
Matx b(####);
Matx c;
c=a.mul(b);
Matx d(a,b,Mul_OP)

template<typename _Tp, typename _T2, int m, int n> static inlineMatxCommaInitializer<_Tp, m, n> operator << (const Matx<_Tp, m, n>& mtx, _T2 val){    MatxCommaInitializer<_Tp, m, n> commaInitializer((Matx<_Tp, m, n>*)&mtx);    return (commaInitializer, val);}template<typename _Tp, int m, int n> inlineMatxCommaInitializer<_Tp, m, n>::MatxCommaInitializer(Matx<_Tp, m, n>* _mtx)    : dst(_mtx), idx(0){}template<typename _Tp, int m, int n> template<typename _T2> inlineMatxCommaInitializer<_Tp, m, n>& MatxCommaInitializer<_Tp, m, n>::operator , (_T2 value){    CV_DbgAssert( idx < m*n );    dst->val[idx++] = saturate_cast<_Tp>(value);    return *this;}template<typename _Tp, int m, int n> inlineMatx<_Tp, m, n> MatxCommaInitializer<_Tp, m, n>::operator *() const{    CV_DbgAssert( idx == n*m );    return *dst;}

一种往已有矩阵添加数的方法,具体情况不清楚。

///////////////////////////// Matx out-of-class operators ////////////////////////////////template<typename _Tp1, typename _Tp2, int m, int n> static inlineMatx<_Tp1, m, n>& operator += (Matx<_Tp1, m, n>& a, const Matx<_Tp2, m, n>& b){    for( int i = 0; i < m*n; i++ )        a.val[i] = saturate_cast<_Tp1>(a.val[i] + b.val[i]);    return a;}template<typename _Tp1, typename _Tp2, int m, int n> static inlineMatx<_Tp1, m, n>& operator -= (Matx<_Tp1, m, n>& a, const Matx<_Tp2, m, n>& b){    for( int i = 0; i < m*n; i++ )        a.val[i] = saturate_cast<_Tp1>(a.val[i] - b.val[i]);    return a;}template<typename _Tp, int m, int n> static inlineMatx<_Tp, m, n> operator + (const Matx<_Tp, m, n>& a, const Matx<_Tp, m, n>& b){    return Matx<_Tp, m, n>(a, b, Matx_AddOp());}template<typename _Tp, int m, int n> static inlineMatx<_Tp, m, n> operator - (const Matx<_Tp, m, n>& a, const Matx<_Tp, m, n>& b){    return Matx<_Tp, m, n>(a, b, Matx_SubOp());}template<typename _Tp, int m, int n> static inlineMatx<_Tp, m, n>& operator *= (Matx<_Tp, m, n>& a, int alpha){    for( int i = 0; i < m*n; i++ )        a.val[i] = saturate_cast<_Tp>(a.val[i] * alpha);    return a;}template<typename _Tp, int m, int n> static inlineMatx<_Tp, m, n>& operator *= (Matx<_Tp, m, n>& a, float alpha){    for( int i = 0; i < m*n; i++ )        a.val[i] = saturate_cast<_Tp>(a.val[i] * alpha);    return a;}template<typename _Tp, int m, int n> static inlineMatx<_Tp, m, n>& operator *= (Matx<_Tp, m, n>& a, double alpha){    for( int i = 0; i < m*n; i++ )        a.val[i] = saturate_cast<_Tp>(a.val[i] * alpha);    return a;}template<typename _Tp, int m, int n> static inlineMatx<_Tp, m, n> operator * (const Matx<_Tp, m, n>& a, int alpha){    return Matx<_Tp, m, n>(a, alpha, Matx_ScaleOp());}template<typename _Tp, int m, int n> static inlineMatx<_Tp, m, n> operator * (const Matx<_Tp, m, n>& a, float alpha){    return Matx<_Tp, m, n>(a, alpha, Matx_ScaleOp());}template<typename _Tp, int m, int n> static inlineMatx<_Tp, m, n> operator * (const Matx<_Tp, m, n>& a, double alpha){    return Matx<_Tp, m, n>(a, alpha, Matx_ScaleOp());}template<typename _Tp, int m, int n> static inlineMatx<_Tp, m, n> operator * (int alpha, const Matx<_Tp, m, n>& a){    return Matx<_Tp, m, n>(a, alpha, Matx_ScaleOp());}template<typename _Tp, int m, int n> static inlineMatx<_Tp, m, n> operator * (float alpha, const Matx<_Tp, m, n>& a){    return Matx<_Tp, m, n>(a, alpha, Matx_ScaleOp());}template<typename _Tp, int m, int n> static inlineMatx<_Tp, m, n> operator * (double alpha, const Matx<_Tp, m, n>& a){    return Matx<_Tp, m, n>(a, alpha, Matx_ScaleOp());}template<typename _Tp, int m, int n> static inlineMatx<_Tp, m, n> operator - (const Matx<_Tp, m, n>& a){    return Matx<_Tp, m, n>(a, -1, Matx_ScaleOp());}template<typename _Tp, int m, int n, int l> static inlineMatx<_Tp, m, n> operator * (const Matx<_Tp, m, l>& a, const Matx<_Tp, l, n>& b){    return Matx<_Tp, m, n>(a, b, Matx_MatMulOp());}template<typename _Tp, int m, int n> static inlineVec<_Tp, m> operator * (const Matx<_Tp, m, n>& a, const Vec<_Tp, n>& b){    Matx<_Tp, m, 1> c(a, b, Matx_MatMulOp());    return (const Vec<_Tp, m>&)(c);}

非成员函数的运算符重载,将重载后的操作定义在类外。

_Tp& operator *(const _Tp &a,const _Tp &b){a=a+b;return a;}
返回引用的意思是返回返回值的引用。
比如上面代码的意思就是返回a的引用
执行c=a*b那么c就是a的引用,而a又是a+b并且这个函数没有定义变量,也就是说没有额外的内存开销,所有使用的变量都是前面程序里面已经有的。这里千万不能有const 因为一旦加上数据保护,那么这个数据就不能再更改了,a就还是a 最后c返回a 的引用没有什么意义

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 飞机没带身份证怎么办 上飞机没带身份证怎么办 机场没带身份证怎么办 儿童坐飞机没有户口本怎么办 不需要行李托运化妆品怎么办 坐飞机被限制了怎么办 坐飞机没买保险怎么办 飞机起飞时难受怎么办 婴儿坐飞机没座位怎么办 转机行李不直达怎么办 儿童自己坐飞机怎么办手续 两岁宝宝发烧怎么办 网上购票待核验怎么办 老人坐飞机找不到登机口怎么办 儿童不能值机怎么办 飞机上旅客刁难怎么办 飞机上婴儿哭闹怎么办 飞机上婴儿啼哭怎么办 飞机儿童陪护手续怎么办 孕妇感冒鼻子堵怎么办 孕妇用了眼药水怎么办 孕妇用眼药水了怎么办 错过了登机时间怎么办 过了登机时间怎么办 孩子不喜欢做作业怎么办 宝宝腿不一样粗怎么办 一个小腿肿了怎么办 左右小腿不一样粗怎么办 小孩不敢自己睡怎么办 小孩不一个人睡怎么办 晚上一个人睡觉害怕怎么办 孩子自己睡害怕怎么办 小孩晚上睡觉怕怎么办 小孩分房睡害怕怎么办 坐飞机不认识字怎么办 科目一不识字怎么办 孩子不自己睡觉怎么办 70岁老人坐高铁怎么办 八岁儿童怎么办护照 第一次坐飞机有点紧张怎么办 坐飞机恐高耳鸣怎么办