首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > C++ >

操作符重载有关问题,哪个编译器是正确的

2012-02-25 
操作符重载问题,哪个编译器是正确的?今天写一个矩阵运算的程序,为了方便,对操作符进行了重载。写的时候是在

操作符重载问题,哪个编译器是正确的?
今天写一个矩阵运算的程序,为了方便,对操作符进行了重载。
写的时候是在VC6下写的,完了又在Dev下编译了一下,发现Dev下竟然不支持连乘。
即不支持   a*b*c
而VC下却是可以编译通过的
到底哪个编译器是正确的?

typedef   struct   _TMatrix   {
double   row[3][3];

}   TMatrix;

TMatrix   operator   *(TMatrix   &T1,TMatrix   &T2)
{
TMatrix   T;
int   i,j,k;
for   (i=0;i <3;i++)
for   (j=0;j <3;j++)
for(k=0;k <3;k++)
T.row[i][j]+=T1.row[i][k]*T2.row[k][j];

return   T;
}

[解决办法]
函数参数用const TMatrix &T1这样
[解决办法]
可以连乘才对. 考虑一下内置类型处理方式, 自定义的类应该模仿它们.

lovewhzlq 的方案不太好. 无论如何返回引用一定是错了.

应该这样吧.
inline const TMatrix operator*(TMatrix & const lhs,TMatrix & const rhs);

参考一下. EC++ 3 , item 21
[解决办法]
临时变量只能做右值,这个是标准的规定……

老实说……这个相当晦涩呢,C++。

TMatrix& t = TMatrix();这个显然也不能通过的。
[解决办法]
一、函数按值返回的是临时变量,不是局部栈。
二、临时变量可以绑定在cosnt reference。
[解决办法]
三、参考 2003-8.5.3

A reference to type “cv1T1” is initialized by an expression of type “cv2T2” as follows:
— If the initializer expression
—— is an lvalue (but is not a bit-field), and “cv1T1” is reference-compatible with “cv2T2,” or
—— has a class type (i.e., T2 is a class type) and can be implicitly converted to an lvalue of type

— Otherwise, the reference shall be to a non-volatile const type (i.e.,cv1shall be const).

不好粘,后面的略了,反正都是const。

简单地说,临时对象只能被 non-volatile const 引用。

[解决办法]
typedef struct _TMatrix {
double row[3][3];

} TMatrix;


TMatrix& operator *(TMatrix T1,TMatrix T2)
{

int i,j,k;
TMatrix *T=new TMatrix;//因为这是堆内存,一般由程序员分配释放,回
for (i=0;i <3;i++)
for (j=0;j <3;j++)
T-> row[i][j]=0;
for (i=0;i <3;i++)
for (j=0;j <3;j++)
for(k=0;k <3;k++)
T-> row[i][j]+=T1.row[i][k]*T2.row[k][j];
return *T;
delete T;//释放内存
}
//这个函数应该没什么问题了,大家看看!!

void main()
{
TMatrix a={2,2,2,2,2,2,2,2,2};
TMatrix b={1,1,1,1,1,1,1,1,1};
TMatrix c={1,1,1,1,1,1,1,1,1};
TMatrix d;
d=(a*b*c);
for (int i=0;i <3;i++)
for (int j=0;j <3;j++)
cout < <d.row[i][j] < < " ";
cout < <endl;
}



[解决办法]
这个确实比较难理解。 iambic() 贴的标准我也看到了。我的疑问是:

TMatrix get_martix()
{
return TMatrix();
}

int main()
{
get_martix() = TMatrix();
}

这样的程序,即使在g++中也是正确的。get_martix可以放在等式的左边(这里是赋值而不是初始化吧),说明get_martix() yeild 一个 lvalue 。那么是否应该符合第一条呢?

—— is an lvalue (but is not a bit-field), and “cv1T1” is reference-compatible with “cv2T2,”

TMatrix(cv1T1)显然是 reference-compatible with TMartix(cv2T2) 的。而TMatrix operator *(TMatrix &T1,TMatrix &T2) 是 an expresion of Type cv2T2 。这样看来,TMatrix& (a reference to cv1T1)是可以用 TMatrix operator *(TMatrix &T1,TMatrix &T2) 的结果初试化的。

标准中后面举的例子都是内建类型的,所以对类类型该怎样理解,比较不放心。虽然我发现在标准中,所有出现临时对象的地方,都赋给了const reference。但是要找到根据还是比较困难的。



但是别急,标准13.3.3.1.4 还有这一句:
A standard conversion sequence cannot be formed if it requires binding a reference to non-const to an rvalue (except when binding an implicit object parameter; see the special rules for that case in 13.3.1). [Note: this means, for example, that a candidate function cannot be a viable function if it has a non-const reference parameter (other than the implicit object parameter) and the corresponding argument is a temporary or would require one to be created to initialize the reference (see 8.5.3). ]
它的正文和Note似乎可以推论出 a temporary 是 an rvalue ;从而 a temporary 不可以赋给a non-const reference parameter 。那么,也许我开始举的例子是一个特例:或者get_martix() = TMatrix(); 是特殊的,或者函数返回的类类型临时对象不受13.3.3.1.4的约束。
该如何看待一个函数的返回值(类类型的临时对象)赋给另一个函数的参数(该对象类型的 non-const reference),确实是一个难题,期待更多的讨论。

但不管怎么说,将 TMatrix operator *(TMatrix &T1,TMatrix &T2)
改成 TMatrix operator *(const TMatrix &T1,const TMatrix &T2)
总是可以的。
也许一些难题之所以成为难题,是因为没有必要去解决它,直接避免它就可以了。

P.S. 标准比较难办的地方是:即使有一个相对通用的条款,只要在其他地方还有一条特殊的(more specified )条款,那么在后者规定的条件下,特殊条款优先通用条款。所以,当看到一个条款时,并不能确定它在所有条件下都成立,还要看其他地方有没有更特殊条款(郁闷!);何况它许多地方都很晦涩的。
[解决办法]
是我前面搞错了,我贴的那部分不足以成为证明。(不过结论应该是对的。)

函数的返回值是一个临时对象,临时对象“应该”是一个rvalue,但是函数返回值可以是rvalue。

我记得《Efective C++》中提到过这个不一致的问题,刚才翻了下没找到……

但是如:

TMatrix operator *(const TMatrix &T1,const TMatrix &T2)

还是应该尽量写成

const TMatrix operator *(const TMatrix &T1,const TMatrix &T2)

以避免

(a * b) = c;

这样的用法。

[解决办法]
右值和const不是一个概念。右值是不能被绑定到const指针和引用上,并非右值就是const。

TMatrix get_martix()
{
return TMatrix();
}

int main()
{
get_martix() = TMatrix();
}
这种写法之所以被支持,是为了类似于这样的做法:

list <int> ListOne;
//.....
ListOne(list <int> (newsize).swap());
这种用法其实也不算少见。

楼上的写法,不合适,返回值不应当写为const变量,为何?
因为标准支持这样做:(a*b).func(),如果返回const变量,这里就只能调用const函数。
[解决办法]
编译器不会错,错的只可能是写程序的人!
不要关心编译器是否符合标准,选择了一种编译器就要去适应它!

热点排行