operator + 应该返回const T& 还是 T& ?

时间:2022-10-29 12:09:57
《D&E》里面说要返回const T&, 为了防止 (a=b)=c;
《Exceptional C++》说要返回 T&,为了与STL的容器兼容。
两个好像都有理……

51 个解决方案

#1


标题错了?

#2


都行,根据需要呗!

#3


楼主,你要理解const引用和非const引用的区别。
d=a+b+c;这种可能产生临时对象的情况,肯定是要const引用

#4


这个都可以吧,看你要怎么用了,,

#5


不对哦~~
重载=难道不是返回一个对象么?怎么返回一个引用了?

class A
{
public:
  A operator=( const A& a)
  {}
};

lz是不是指参数哦?

#6


呵呵,都忘的差不多了!!

看看这个:

http://www.cnblogs.com/fxwdl/archive/2008/01/15/1039812.html

应该有帮助!

#7


C++ Primer上是返回T

#8


引用 1 楼 paidfighting 的回复:
标题错了?

呃,对于二元运算符都一样的
(a+b)=c;

#9


引用 5 楼 hqin6 的回复:
不对哦~~ 
重载=难道不是返回一个对象么?怎么返回一个引用了? 

class A 

public: 
  A operator=(const A& a) 
  {} 
}; 

lz是不是指参数哦? 


我错了!~~

#10


这个还是要看具体的需求

#11


引用 7 楼 oldmanzhao 的回复:
C++ Primer上是返回T

我特意查了,是返回T&,估计没人会返回T,嘿嘿

#12


引用 3 楼 juvily 的回复:
楼主,你要理解const引用和非const引用的区别。 
d=a+b+c;这种可能产生临时对象的情况,肯定是要const引用 

这里不见得要用const吧?只能说明要用引用,嘿嘿

#13


返回什么不重要,参数是一定要用const引用

#14


引用 13 楼 ypyf3000 的回复:
返回什么不重要,参数是一定要用const引用

“返回什么不重要?”放屁放屁,臭不可闻……

#15


引用 8 楼 lingol 的回复:
引用 1 楼 paidfighting 的回复:
标题错了? 
 
呃,对于二元运算符都一样的 
(a+b)=c;

+要返回const T

#16


为什么要返回const T&呢,你希望一个对象不能在同一个表达式里两次被赋值么?

(a=b)=c有问题么?

#17


这个没有绝对的标准,一般只根据一些惯例和你的设计意图来决定是返回const T&, T&, T

#18


是operator+还是operator=?
operator=为了与c++内置类型保持一致,应该返回T&而不是const T&。

#19


引用 17 楼 matrixdwy 的回复:
这个没有绝对的标准,一般只根据一些惯例和你的设计意图来决定是返回const T&, T&, T

#20


#include <iostream>
using namespace std;

class T
{
    public: 
        int i;  
        void operator=(const T t2)
        {       
            this->i=t2.i;
        }       
};

//void operator=(T t1, const T t2);   //·ÇÀà³ÉÔ±²Ù×÷·ûÖØÔØ

int main()
{
    T t1;
    t1.i = 1;
    T t2;
    t2 = t1;
    cout<<t2.i;
}


=================
我怎么没看懂你们说的意思啊,我这样不是也行吗?返回值是void型的啊。

#21


OK,算我写错标题了,这里只讨论operater =
16楼,这样写本身没有大问题,还有一个问题是如果你本来想

if((a=b) == c)
{
...
}

一不小心写成(a=b)=c,这是完全符合语法的,编译器连警告都不会给一个,等你debug时就知惨……
18楼,你的类不能连续赋值。


PS:15楼,operater + 返回const T应该没有效率的问题吧?
我对临时对象的生存期不太懂——看《对象模型》还未看到那一部份。

#22



//无论如何,双目运算符都不要返回带&的东东,而且要const 
friend const T operator+( const T& lhs, const T& rhs );
//单目运算符尽量返回带&的东东,只有后置自增自减这两个运算符按照双目处理
T& operator=( const T& other );

以上

#23


引用 21 楼 lingol 的回复:
OK,算我写错标题了,这里只讨论operater = 
16楼,这样写本身没有大问题,还有一个问题是如果你本来想 

C/C++ code
if((a=b) == c)
{
...
}


一不小心写成(a=b)=c,这是完全符合语法的,编译器连警告都不会给一个,等你debug时就知惨…… 
18楼,你的类不能连续赋值。 


PS:15楼,operater + 返回const T应该没有效率的问题吧? 
我对临时对象的生存期不太懂——看《对象模型》还未看到那一部份。 


现代编译器还有在if里赋值不产生警告的?VC6都有这个警告。另外,返回T&仅是为了与内置类型保持一样的语义,如果你有理由不用这种特性,那返回const T&也没关系。
const T编译器应该能优化掉,但是const T&更好。

#24


引用 22 楼 fallening 的回复:

//无论如何,双目运算符都不要返回带&的东东,而且要const 
friend const T operator+( const T& lhs, const T& rhs );
//单目运算符尽量返回带&的东东,只有后置自增自减这两个运算符按照双目处理
T& operator=( const T& other );

以上 


授之以渔啊,条条框框的就是不能使人信服

#25


VS2008 有个P警告,只是如果类型T不能隐式转换为bool的话编译不过罢了。
这个就没有警告:

int oo, pp = 1, qq = 0;
if ((oo = pp) = qq)
cout<<"OK"<<endl;

#26


再贴一个真实一点的,同样VS08没有警告:

// test.cpp
#include <iostream>

class A
{
public:
A(int i = 0) : num(i) {};
A& operator = (const A& source)
{
this->num = source.num;
return(*this);
}
operator int()
{
return (num);
}
private:
int num;
};
int main()
{
A i, j(1), k(2);
// j = k = i;
// (j = k) = i;
if ((j=k) = i)
std::cout<<"OK"<<endl;
return (0);
}

#27


VS08有没有警告我不知道,我只知道gcc上是这么提示的
test.cpp: In function 'int main()':
test.cpp:27: error: 'endl' was not declared in this scope

#28


还是那句话,返回T&仅是为了与内置类型保持一样的语义,如果你有理由不用这种特性,那返回const T&也没关系。

#29


看需要吧

#30


VS08有没有警告我不知道,我只知道gcc上是这么提示的 
test.cpp: In function 'int main()': 
test.cpp:27: error: 'endl' was not declared in this scope 
呃,的确是疏漏了,我原来是using namespace std;的……

std::cout<<"OK"<<std::endl;

只是这和我们讨论的问题有何相干?

#31


引用 24 楼 lingol 的回复:
[Quote=引用 22 楼 fallening 的回复:]
C/C++ code//无论如何,双目运算符都不要返回带&的东东,而且要constfriendconstToperator+(constT&lhs,constT&rhs );//单目运算符尽量返回带&的东东,只有后置自增自减这两个运算符按照双目处理T&operator=(constT&other );
以上


授之以渔啊,条条框框的就是不能使人信服
[/Quote]
$ cat a.cc
#include <iostream>
using namespace std;

class A
{
    public:
        A():data_(0){}

        ~A(){}

        template< class T>
        A( const T& other )
        {
            operator = (other );
        }

        template< class T>
        A& operator = ( const T& other )
        {
            copy( other );
            return *this;
        }

        A& operator +=( const A& other )
        {
            data_ += other.data_;
            return *this;
        }

        operator bool()
        {
            return data_ ? true : false;
        }

        friend const A operator +( const A& lhs, const A& rhs )
        {
            A tmp( lhs );
            tmp += rhs;
            return tmp;
        }

        //attention, return a reference
        friend ostream& operator << ( ostream& os, const A& rhs )
        {
            return rhs.print( os );
        }

    private:
        int data_;
        
        void copy( const A& other )
        {
            data_ = other.data_;
        }
        
        void copy( const int& other )
        {
            data_ = other;
        }
        
        ostream& print( ostream& os ) const
        {
            return os << data_;

        operator bool()
        {
            return data_ ? true : false;
        }

        friend const A operator +( const A& lhs, const A& rhs )
        {
            A tmp( lhs );
            tmp += rhs;
            return tmp;
        }

        //attention, return a reference
        friend ostream& operator << ( ostream& os, const A& rhs )
        {
            return rhs.print( os );
        }

    private:
        int data_;
        
        void copy( const A& other )
        {
            data_ = other.data_;
        }
        
        void copy( const int& other )
        {
            data_ = other;
        }
        
        ostream& print( ostream& os ) const
        {
            return os << data_;

        operator bool()
        {
            return data_ ? true : false;
        }

        friend const A operator +( const A& lhs, const A& rhs )
        {
            A tmp( lhs );
            tmp += rhs;
            return tmp;
        }

        //attention, return a reference
        friend ostream& operator << ( ostream& os, const A& rhs )
        {
            return rhs.print( os );
        }

    private:
        int data_;
        
        void copy( const A& other )
        {
            data_ = other.data_;
        }
        
        void copy( const int& other )
        {
            data_ = other;
        }
        
        ostream& print( ostream& os ) const
        {
            return os << data_;

        operator bool()
        {
            return data_ ? true : false;
        }

        friend const A operator +( const A& lhs, const A& rhs )
        {
            A tmp( lhs );
            tmp += rhs;
            return tmp;
        }

        //attention, return a reference
        friend ostream& operator << ( ostream& os, const A& rhs )
        {
            return rhs.print( os );
        }

    private:
        int data_;
        
        void copy( const A& other )
        {
            data_ = other.data_;
        }
        
        void copy( const int& other )
        {
            data_ = other;
        }
        
        ostream& print( ostream& os ) const
        {
            return os << data_;
        }

};

int main()
{
    A s;
    A t;

    s = 5;
    t = 10;
    cout << s << endl;

    s = s + t;
    cout << s << endl;
    
    s += t;
    cout << s << endl;

    s += 7;
    cout << s << endl;

    if (  t = ( s = 18 ) = 19 )
        cout << t << endl;


    return 0;
}

$ g++ -o a a.cc -Wall && ./a
a.cc: In function ‘int main()’:
a.cc:86: warning: suggest parentheses around assignment used as truth value
5
15
25
32
19

#32


貌似楼上源代码复制的时候又多点了一下,重新贴了
#include <iostream>
using namespace std;

class A
{
    public:
        A():data_(0){}

        ~A(){}

        template< class T>
        A( const T& other )
        {
            operator = (other );
        }

        template< class T>
        A& operator = ( const T& other )
        {
            copy( other );
            return *this;
        }

        A& operator +=( const A& other )
        {
            data_ += other.data_;
            return *this;
        }

        operator bool()
        {
            return data_ ? true : false;
        }

        friend const A operator +( const A& lhs, const A& rhs )
        {
            A tmp( lhs );
            tmp += rhs;
            return tmp;
        }

        //attention, return a reference
        friend ostream& operator << ( ostream& os, const A& rhs )
        {
            return rhs.print( os );
        }

    private:
        int data_;
        
        void copy( const A& other )
        {
            data_ = other.data_;
        }
        
        void copy( const int& other )
        {
            data_ = other;
        }
        
        ostream& print( ostream& os ) const
        {
            return os << data_;
        }

};

int main()
{
    A s;
    A t;

    s = 5;
    t = 10;
    cout << s << endl;

    s = s + t;
    cout << s << endl;
    
    s += t;
    cout << s << endl;

    s += 7;
    cout << s << endl;

    if (  t = ( s = 18 ) = 19 )
        cout << t << endl;


    return 0;
}







#33


楼上的等下再拜读,27楼,你搬gcc出来唬人么:
lingol@Lion:~/cpp$ cat test.cpp

#include <iostream>
using namespace std;

class A
{
public:
A(int i = 0) : num(i) {};
A& operator = (const A& source)
{
this->num = source.num;
return(*this);
}
operator int()
{
return num;
}
private:
int num;
};

int main()
{
A i, j(1), k(2);
if ((j=k) = i)
std::cout<<"OK"<<std::endl;
return(0);
}

lingol@Lion:~/cpp$ g++ -o test test.cpp

#34


P也没警告一个……

#35


operator+ 返回引用,至于是否常量,个人觉得不一定,看情况而定

毕竟重载操作符+的对象用途是不定的

#36


很感谢31楼不辞劳苦写了这么完整的示例。不过只怕误解了我的意思,
我说“授之以渔”,不是想请教 如何,而是 为何
从32楼的代码中看不出 为何 无论如何,双目运算符都不要返回带&的东东,而且要const
可能本人悟性不够,看不出来,还请fallening再讲解一下

#37


那些说“视情况而定”、“根据需要”之类各打五十大板的仁兄们,麻烦总结一下什么
“情况”下用const T&,什么“需要”下用 T&,否则等于什么都没说。

#38


返回的类型和你的需求有关系,当然对于语法来说,都是正确的,所以没有对错之分,明白吗?

#39


我搬gcc是因为我没有VS08。
你的代码问题在于operator int();
那么讨论能不能返回T&不如先讨论一下要不要定义类型转换操作符。

#40


我倒是总结过,可你不信也没办法。

返回T&是为了与内置类型保持一样的语法语义,如果你有理由不用这种特性(比如你定义了类型转换操作符,又怕出错),那返回const T&也没关系。

#41


引用 36 楼 lingol 的回复:
很感谢31楼不辞劳苦写了这么完整的示例。不过只怕误解了我的意思,
我说“授之以渔”,不是想请教如何,而是为何。
从32楼的代码中看不出为何无论如何,双目运算符都不要返回带&的东东,而且要const
可能本人悟性不够,看不出来,还请fallening再讲解一下

前人之叙备矣
http://www.google.com/search?hl=en&q=GotW+Class+Mechanics&btnG=Google+Search

#42


LZ的态度有问题,好像这里的人都欠你钱似的

#43


对于操作符重载,惯例是:内置类型怎么做,咱就怎么做。
当然,理由充分,惯例也是可以打破的。
不过大多数时候懒得去多想,遵照惯例就OK了。
如此而已。

#44


引用 22 楼 fallening 的回复:
C/C++ code//无论如何,双目运算符都不要返回带&的东东,而且要constfriendconstToperator+(constT&lhs,constT&rhs );//单目运算符尽量返回带&的东东,只有后置自增自减这两个运算符按照双目处理T&operator=(constT&other );
以上

这是潜规则,要遵从 

另外,如果注重效率、临时对象等问题,尽量用其他一些技术实现,如模板元编程、表达式延迟计算等

#45


41楼,怎么解释这个?貌似和你的“ 无论如何,双目运算符都不要返回带&的东东,而且要const ”
不怎么和谐啊,嘿嘿
http://www.gotw.ca/gotw/004.htm
4. ERROR: operator+ should not modify this object's value. It should return a temporary object containing the sum. Note that this return type should be "const Complex" (not just "Complex") in order to prevent usage like "a+b=c".


另外,本人看不惯说话未经大脑者、信口开河者、不懂装懂者、教条主义者,这些人的回复无益于
技术讨论。我看不惯就批,不行么?

#46


弊,看漏了,是"const Complex" ,楼上的可以删了。(这里怎么不让人删自己的帖子?)
41楼,对不起对不起。

#47


引用 39 楼 Maxwell 的回复:
我搬gcc是因为我没有VS08。 
你的代码问题在于operator int(); 
那么讨论能不能返回T&不如先讨论一下要不要定义类型转换操作符。

引用 25 楼 lingol 的回复:
VS2008 有个P警告,只是如果类型T不能隐式转换为bool的话编译不过罢了。 


前面已经说得很清楚了,这里仅仅为了演示。
你总不能排除某个类需要转换为int,又要重载operator = 吧?

#48


你当时说更真实的例子,我以为你是编译通过的,因此给你贴个错误。

就像=有返回T&和const T&两种一样,转换为int也有多种方式,比如AsInt(),可能更被推荐使用。
你说的风险是由两个原因共同作用造成的,因此不能说非要这个问题上坚持错的,把责任都怪到另一种头上。

每个人都要根据自己的情况来选择,如果周围环境不好,不如追求安全,就定义const T&,标准扔在一边,如果是我自己写代码全部是由我控制,我选择用T&与内置类型保持一致。所以告诉你什么情况下用那种就太教条了,不如你明白各有什么优缺点,自己选择。

#49


楼上说的是有道理的,应该明白原理,然后自行决定。
另外,重载类型转换操作符确实应该慎用,因为容易造成一些令人头痛的问题,就连可以起隐式转换作用的单参构造函数都应该声明为explicit。
STL里的string,没有重载operator const char*,而是提供了一个成员函数c_str(),就是基于这种考虑。

#50


我认为是T,因为如果返回CONST ,那么则意味着不能进行连续运算!

当然得看那种情况更合适你的应用...

#1


标题错了?

#2


都行,根据需要呗!

#3


楼主,你要理解const引用和非const引用的区别。
d=a+b+c;这种可能产生临时对象的情况,肯定是要const引用

#4


这个都可以吧,看你要怎么用了,,

#5


不对哦~~
重载=难道不是返回一个对象么?怎么返回一个引用了?

class A
{
public:
  A operator=( const A& a)
  {}
};

lz是不是指参数哦?

#6


呵呵,都忘的差不多了!!

看看这个:

http://www.cnblogs.com/fxwdl/archive/2008/01/15/1039812.html

应该有帮助!

#7


C++ Primer上是返回T

#8


引用 1 楼 paidfighting 的回复:
标题错了?

呃,对于二元运算符都一样的
(a+b)=c;

#9


引用 5 楼 hqin6 的回复:
不对哦~~ 
重载=难道不是返回一个对象么?怎么返回一个引用了? 

class A 

public: 
  A operator=(const A& a) 
  {} 
}; 

lz是不是指参数哦? 


我错了!~~

#10


这个还是要看具体的需求

#11


引用 7 楼 oldmanzhao 的回复:
C++ Primer上是返回T

我特意查了,是返回T&,估计没人会返回T,嘿嘿

#12


引用 3 楼 juvily 的回复:
楼主,你要理解const引用和非const引用的区别。 
d=a+b+c;这种可能产生临时对象的情况,肯定是要const引用 

这里不见得要用const吧?只能说明要用引用,嘿嘿

#13


返回什么不重要,参数是一定要用const引用

#14


引用 13 楼 ypyf3000 的回复:
返回什么不重要,参数是一定要用const引用

“返回什么不重要?”放屁放屁,臭不可闻……

#15


引用 8 楼 lingol 的回复:
引用 1 楼 paidfighting 的回复:
标题错了? 
 
呃,对于二元运算符都一样的 
(a+b)=c;

+要返回const T

#16


为什么要返回const T&呢,你希望一个对象不能在同一个表达式里两次被赋值么?

(a=b)=c有问题么?

#17


这个没有绝对的标准,一般只根据一些惯例和你的设计意图来决定是返回const T&, T&, T

#18


是operator+还是operator=?
operator=为了与c++内置类型保持一致,应该返回T&而不是const T&。

#19


引用 17 楼 matrixdwy 的回复:
这个没有绝对的标准,一般只根据一些惯例和你的设计意图来决定是返回const T&, T&, T

#20


#include <iostream>
using namespace std;

class T
{
    public: 
        int i;  
        void operator=(const T t2)
        {       
            this->i=t2.i;
        }       
};

//void operator=(T t1, const T t2);   //·ÇÀà³ÉÔ±²Ù×÷·ûÖØÔØ

int main()
{
    T t1;
    t1.i = 1;
    T t2;
    t2 = t1;
    cout<<t2.i;
}


=================
我怎么没看懂你们说的意思啊,我这样不是也行吗?返回值是void型的啊。

#21


OK,算我写错标题了,这里只讨论operater =
16楼,这样写本身没有大问题,还有一个问题是如果你本来想

if((a=b) == c)
{
...
}

一不小心写成(a=b)=c,这是完全符合语法的,编译器连警告都不会给一个,等你debug时就知惨……
18楼,你的类不能连续赋值。


PS:15楼,operater + 返回const T应该没有效率的问题吧?
我对临时对象的生存期不太懂——看《对象模型》还未看到那一部份。

#22



//无论如何,双目运算符都不要返回带&的东东,而且要const 
friend const T operator+( const T& lhs, const T& rhs );
//单目运算符尽量返回带&的东东,只有后置自增自减这两个运算符按照双目处理
T& operator=( const T& other );

以上

#23


引用 21 楼 lingol 的回复:
OK,算我写错标题了,这里只讨论operater = 
16楼,这样写本身没有大问题,还有一个问题是如果你本来想 

C/C++ code
if((a=b) == c)
{
...
}


一不小心写成(a=b)=c,这是完全符合语法的,编译器连警告都不会给一个,等你debug时就知惨…… 
18楼,你的类不能连续赋值。 


PS:15楼,operater + 返回const T应该没有效率的问题吧? 
我对临时对象的生存期不太懂——看《对象模型》还未看到那一部份。 


现代编译器还有在if里赋值不产生警告的?VC6都有这个警告。另外,返回T&仅是为了与内置类型保持一样的语义,如果你有理由不用这种特性,那返回const T&也没关系。
const T编译器应该能优化掉,但是const T&更好。

#24


引用 22 楼 fallening 的回复:

//无论如何,双目运算符都不要返回带&的东东,而且要const 
friend const T operator+( const T& lhs, const T& rhs );
//单目运算符尽量返回带&的东东,只有后置自增自减这两个运算符按照双目处理
T& operator=( const T& other );

以上 


授之以渔啊,条条框框的就是不能使人信服

#25


VS2008 有个P警告,只是如果类型T不能隐式转换为bool的话编译不过罢了。
这个就没有警告:

int oo, pp = 1, qq = 0;
if ((oo = pp) = qq)
cout<<"OK"<<endl;

#26


再贴一个真实一点的,同样VS08没有警告:

// test.cpp
#include <iostream>

class A
{
public:
A(int i = 0) : num(i) {};
A& operator = (const A& source)
{
this->num = source.num;
return(*this);
}
operator int()
{
return (num);
}
private:
int num;
};
int main()
{
A i, j(1), k(2);
// j = k = i;
// (j = k) = i;
if ((j=k) = i)
std::cout<<"OK"<<endl;
return (0);
}

#27


VS08有没有警告我不知道,我只知道gcc上是这么提示的
test.cpp: In function 'int main()':
test.cpp:27: error: 'endl' was not declared in this scope

#28


还是那句话,返回T&仅是为了与内置类型保持一样的语义,如果你有理由不用这种特性,那返回const T&也没关系。

#29


看需要吧

#30


VS08有没有警告我不知道,我只知道gcc上是这么提示的 
test.cpp: In function 'int main()': 
test.cpp:27: error: 'endl' was not declared in this scope 
呃,的确是疏漏了,我原来是using namespace std;的……

std::cout<<"OK"<<std::endl;

只是这和我们讨论的问题有何相干?

#31


引用 24 楼 lingol 的回复:
[Quote=引用 22 楼 fallening 的回复:]
C/C++ code//无论如何,双目运算符都不要返回带&的东东,而且要constfriendconstToperator+(constT&lhs,constT&rhs );//单目运算符尽量返回带&的东东,只有后置自增自减这两个运算符按照双目处理T&operator=(constT&other );
以上


授之以渔啊,条条框框的就是不能使人信服
[/Quote]
$ cat a.cc
#include <iostream>
using namespace std;

class A
{
    public:
        A():data_(0){}

        ~A(){}

        template< class T>
        A( const T& other )
        {
            operator = (other );
        }

        template< class T>
        A& operator = ( const T& other )
        {
            copy( other );
            return *this;
        }

        A& operator +=( const A& other )
        {
            data_ += other.data_;
            return *this;
        }

        operator bool()
        {
            return data_ ? true : false;
        }

        friend const A operator +( const A& lhs, const A& rhs )
        {
            A tmp( lhs );
            tmp += rhs;
            return tmp;
        }

        //attention, return a reference
        friend ostream& operator << ( ostream& os, const A& rhs )
        {
            return rhs.print( os );
        }

    private:
        int data_;
        
        void copy( const A& other )
        {
            data_ = other.data_;
        }
        
        void copy( const int& other )
        {
            data_ = other;
        }
        
        ostream& print( ostream& os ) const
        {
            return os << data_;

        operator bool()
        {
            return data_ ? true : false;
        }

        friend const A operator +( const A& lhs, const A& rhs )
        {
            A tmp( lhs );
            tmp += rhs;
            return tmp;
        }

        //attention, return a reference
        friend ostream& operator << ( ostream& os, const A& rhs )
        {
            return rhs.print( os );
        }

    private:
        int data_;
        
        void copy( const A& other )
        {
            data_ = other.data_;
        }
        
        void copy( const int& other )
        {
            data_ = other;
        }
        
        ostream& print( ostream& os ) const
        {
            return os << data_;

        operator bool()
        {
            return data_ ? true : false;
        }

        friend const A operator +( const A& lhs, const A& rhs )
        {
            A tmp( lhs );
            tmp += rhs;
            return tmp;
        }

        //attention, return a reference
        friend ostream& operator << ( ostream& os, const A& rhs )
        {
            return rhs.print( os );
        }

    private:
        int data_;
        
        void copy( const A& other )
        {
            data_ = other.data_;
        }
        
        void copy( const int& other )
        {
            data_ = other;
        }
        
        ostream& print( ostream& os ) const
        {
            return os << data_;

        operator bool()
        {
            return data_ ? true : false;
        }

        friend const A operator +( const A& lhs, const A& rhs )
        {
            A tmp( lhs );
            tmp += rhs;
            return tmp;
        }

        //attention, return a reference
        friend ostream& operator << ( ostream& os, const A& rhs )
        {
            return rhs.print( os );
        }

    private:
        int data_;
        
        void copy( const A& other )
        {
            data_ = other.data_;
        }
        
        void copy( const int& other )
        {
            data_ = other;
        }
        
        ostream& print( ostream& os ) const
        {
            return os << data_;
        }

};

int main()
{
    A s;
    A t;

    s = 5;
    t = 10;
    cout << s << endl;

    s = s + t;
    cout << s << endl;
    
    s += t;
    cout << s << endl;

    s += 7;
    cout << s << endl;

    if (  t = ( s = 18 ) = 19 )
        cout << t << endl;


    return 0;
}

$ g++ -o a a.cc -Wall && ./a
a.cc: In function ‘int main()’:
a.cc:86: warning: suggest parentheses around assignment used as truth value
5
15
25
32
19

#32


貌似楼上源代码复制的时候又多点了一下,重新贴了
#include <iostream>
using namespace std;

class A
{
    public:
        A():data_(0){}

        ~A(){}

        template< class T>
        A( const T& other )
        {
            operator = (other );
        }

        template< class T>
        A& operator = ( const T& other )
        {
            copy( other );
            return *this;
        }

        A& operator +=( const A& other )
        {
            data_ += other.data_;
            return *this;
        }

        operator bool()
        {
            return data_ ? true : false;
        }

        friend const A operator +( const A& lhs, const A& rhs )
        {
            A tmp( lhs );
            tmp += rhs;
            return tmp;
        }

        //attention, return a reference
        friend ostream& operator << ( ostream& os, const A& rhs )
        {
            return rhs.print( os );
        }

    private:
        int data_;
        
        void copy( const A& other )
        {
            data_ = other.data_;
        }
        
        void copy( const int& other )
        {
            data_ = other;
        }
        
        ostream& print( ostream& os ) const
        {
            return os << data_;
        }

};

int main()
{
    A s;
    A t;

    s = 5;
    t = 10;
    cout << s << endl;

    s = s + t;
    cout << s << endl;
    
    s += t;
    cout << s << endl;

    s += 7;
    cout << s << endl;

    if (  t = ( s = 18 ) = 19 )
        cout << t << endl;


    return 0;
}







#33


楼上的等下再拜读,27楼,你搬gcc出来唬人么:
lingol@Lion:~/cpp$ cat test.cpp

#include <iostream>
using namespace std;

class A
{
public:
A(int i = 0) : num(i) {};
A& operator = (const A& source)
{
this->num = source.num;
return(*this);
}
operator int()
{
return num;
}
private:
int num;
};

int main()
{
A i, j(1), k(2);
if ((j=k) = i)
std::cout<<"OK"<<std::endl;
return(0);
}

lingol@Lion:~/cpp$ g++ -o test test.cpp

#34


P也没警告一个……

#35


operator+ 返回引用,至于是否常量,个人觉得不一定,看情况而定

毕竟重载操作符+的对象用途是不定的

#36


很感谢31楼不辞劳苦写了这么完整的示例。不过只怕误解了我的意思,
我说“授之以渔”,不是想请教 如何,而是 为何
从32楼的代码中看不出 为何 无论如何,双目运算符都不要返回带&的东东,而且要const
可能本人悟性不够,看不出来,还请fallening再讲解一下

#37


那些说“视情况而定”、“根据需要”之类各打五十大板的仁兄们,麻烦总结一下什么
“情况”下用const T&,什么“需要”下用 T&,否则等于什么都没说。

#38


返回的类型和你的需求有关系,当然对于语法来说,都是正确的,所以没有对错之分,明白吗?

#39


我搬gcc是因为我没有VS08。
你的代码问题在于operator int();
那么讨论能不能返回T&不如先讨论一下要不要定义类型转换操作符。

#40


我倒是总结过,可你不信也没办法。

返回T&是为了与内置类型保持一样的语法语义,如果你有理由不用这种特性(比如你定义了类型转换操作符,又怕出错),那返回const T&也没关系。

#41


引用 36 楼 lingol 的回复:
很感谢31楼不辞劳苦写了这么完整的示例。不过只怕误解了我的意思,
我说“授之以渔”,不是想请教如何,而是为何。
从32楼的代码中看不出为何无论如何,双目运算符都不要返回带&的东东,而且要const
可能本人悟性不够,看不出来,还请fallening再讲解一下

前人之叙备矣
http://www.google.com/search?hl=en&q=GotW+Class+Mechanics&btnG=Google+Search

#42


LZ的态度有问题,好像这里的人都欠你钱似的

#43


对于操作符重载,惯例是:内置类型怎么做,咱就怎么做。
当然,理由充分,惯例也是可以打破的。
不过大多数时候懒得去多想,遵照惯例就OK了。
如此而已。

#44


引用 22 楼 fallening 的回复:
C/C++ code//无论如何,双目运算符都不要返回带&的东东,而且要constfriendconstToperator+(constT&lhs,constT&rhs );//单目运算符尽量返回带&的东东,只有后置自增自减这两个运算符按照双目处理T&operator=(constT&other );
以上

这是潜规则,要遵从 

另外,如果注重效率、临时对象等问题,尽量用其他一些技术实现,如模板元编程、表达式延迟计算等

#45


41楼,怎么解释这个?貌似和你的“ 无论如何,双目运算符都不要返回带&的东东,而且要const ”
不怎么和谐啊,嘿嘿
http://www.gotw.ca/gotw/004.htm
4. ERROR: operator+ should not modify this object's value. It should return a temporary object containing the sum. Note that this return type should be "const Complex" (not just "Complex") in order to prevent usage like "a+b=c".


另外,本人看不惯说话未经大脑者、信口开河者、不懂装懂者、教条主义者,这些人的回复无益于
技术讨论。我看不惯就批,不行么?

#46


弊,看漏了,是"const Complex" ,楼上的可以删了。(这里怎么不让人删自己的帖子?)
41楼,对不起对不起。

#47


引用 39 楼 Maxwell 的回复:
我搬gcc是因为我没有VS08。 
你的代码问题在于operator int(); 
那么讨论能不能返回T&不如先讨论一下要不要定义类型转换操作符。

引用 25 楼 lingol 的回复:
VS2008 有个P警告,只是如果类型T不能隐式转换为bool的话编译不过罢了。 


前面已经说得很清楚了,这里仅仅为了演示。
你总不能排除某个类需要转换为int,又要重载operator = 吧?

#48


你当时说更真实的例子,我以为你是编译通过的,因此给你贴个错误。

就像=有返回T&和const T&两种一样,转换为int也有多种方式,比如AsInt(),可能更被推荐使用。
你说的风险是由两个原因共同作用造成的,因此不能说非要这个问题上坚持错的,把责任都怪到另一种头上。

每个人都要根据自己的情况来选择,如果周围环境不好,不如追求安全,就定义const T&,标准扔在一边,如果是我自己写代码全部是由我控制,我选择用T&与内置类型保持一致。所以告诉你什么情况下用那种就太教条了,不如你明白各有什么优缺点,自己选择。

#49


楼上说的是有道理的,应该明白原理,然后自行决定。
另外,重载类型转换操作符确实应该慎用,因为容易造成一些令人头痛的问题,就连可以起隐式转换作用的单参构造函数都应该声明为explicit。
STL里的string,没有重载operator const char*,而是提供了一个成员函数c_str(),就是基于这种考虑。

#50


我认为是T,因为如果返回CONST ,那么则意味着不能进行连续运算!

当然得看那种情况更合适你的应用...