樱花流逝
为什么用不同的软件输出结果会不同?

总之问题是这样的[mw_shl_code=applescript,true]#include *本站禁止HTML标签噢*

using namespace std;

class point{

private:

int x, y;

public:

point(int a = 0, int b = 0){

x = a;

y = b;

}

point(point &p);

int getx(){

return x;

}

int gety(){

return y;

}

};

point::point(point &p){

x = p.x + 10;[mw_shl_code=applescript,true]point::point(point &p){

x = p.x + 10;

y = p.y + 20;

cout << "调用拷贝构造函数" << endl;

}

y = p.y + 20;

cout << "调用拷贝构造函数" << endl;

}

void f(point &p){

cout << p.getx() << " " << p.gety() << endl;

}

point g(){

point q(3, 5);

return q;

}

int main()

{

point p1(2, 4);

point p2(p1);

cout << p2.getx() << " " << p2.gety() << endl;

f(p2);

p2 = g();

cout << p2.getx() << " " << p2.gety() << endl;

system("pause");

return 0;

}

[/mw_shl_code]

用cb编译运行的得到的结果是这样的

而用vs2013编译得到的结果是这样的

虽然乱码也是问题。。。

但主要是为什么使用vs2013时在执行[mw_shl_code=applescript,true]p2 = g();[/mw_shl_code]时调用了

[mw_shl_code=applescript,true]point::point(point &p){

x = p.x + 10;

y = p.y + 20;

cout << "调用拷贝构造函数" << endl;

}[/mw_shl_code]

而cb没有这一步?

Shino_Asada
展开Biu

本帖最后由 Shino_Asada 于 2015-10-4 13:52 编辑

point p2(p1);

这个调用是没问题的,因为p1是左值

会输出"调用拷贝构造函数"

p2 = g();

g返回右值

point&

非const左值引用不能引用右值,所以不会调用你的拷贝构造函数

CB调用了编译器合成的拷贝构造函数,应该是这个样子的

Point::Point(const Point&);

你也看到了,p2.x和y和g返回的的point一样

拷贝构造函数不应该改变被拷贝对象,所以应该是》》》》const《《《《《 Point&

VS的嘛……233333333嘛~至于f(p2);

f接受的是Point&

所以不会发生拷贝

(小声:引用的底层实现一般是指针哟)

[查看全文]
张全蛋
展开Biu

本帖最后由 张全蛋 于 2015-9-20 01:34 编辑

我已经在MSDN上看到了关于RVO(返回值优化)和NRVO(命名返回值优化)的介绍了,说白了你遇到的问题就是现代编译器为了提高程序运行效率优化搞出来的鬼。而在VS上,编译debug版会调用复制构造函数,但编译release版并不会,跟Devcpp的结果一样。

[查看全文]
张全蛋
展开Biu

本帖最后由 张全蛋 于 2015-9-19 11:28 编辑

樱花流逝 发表于 2015-9-18 12:21

楼上那个是我自己

我的意思是按调用拷贝构造函数的规则,这段代码应该要调用三次,但vs只调用了两 ...

你可以搜下C++的返回值优化,这个优化程度跟编译器有关。CSDN论坛上有个类似的情况,里面的回复中应该能找到你想要的答案 http://bbs.csdn.net/topics/390803716

[查看全文]
张全蛋
展开Biu

樱花流逝 发表于 2015-9-18 12:21

楼上那个是我自己

我的意思是按调用拷贝构造函数的规则,这段代码应该要调用三次,但vs只调用了两 ...

我那个VS2013调用了3次,Devcpp调用了2次。

[查看全文]
樱花流逝
展开Biu

番茄星人 发表于 2015-9-17 00:11

原理上楼上已经说了。

至于为什么vs在p2 = g(); 会调用拷贝

我只能猜

楼上那个是我自己@@10!!

我的意思是按调用拷贝构造函数的规则,这段代码应该要调用三次,但vs只调用了两次,cb只调用了一次(还用一次应该是调用了但不知为何没有显示提示语句)。我想问的是这个。。。

[查看全文]
樱花流逝
展开Biu

番茄星人 发表于 2015-9-17 00:11

原理上楼上已经说了。

至于为什么vs在p2 = g(); 会调用拷贝

我只能猜

楼上那个是我自己@@10!!

我的意思是按调用拷贝构造函数的规则,这段代码应该要调用三次,但vs只调用了两次,cb只调用了一次(还用一次应该是调用了但不知为何没有显示提示语句)。我想问的是这个。。。

[查看全文]
番茄星人
展开Biu

原理上楼上已经说了。

至于为什么vs在p2 = g(); 会调用拷贝

我只能猜

类之间直接赋值会调用拷贝复制函数(PS:不是拷贝构造),也就是 = 的重载函数,前提是你重载了这个函数

明显你是没有重载的,所以至于这个重载的形态是什么,那应该由编译器来默认决定了。

所以有可能是在cb编译器上,它会帮你生成一个默认的拷贝复制函数

然而VS的编译器采用的策略则是,用你写的拷贝构造来当拷贝复制

以上纯属猜测,编译器那些东西要看手册才知道

[查看全文]
樱花流逝
展开Biu

去查了一下调用拷贝构造函数的情形

在C++中,下面三种对象需要调用拷贝构造函数:

1) 一个对象以值传递的方式传入函数体;

2) 一个对象以值传递的方式从函数返回;

3) 一个对象需要通过另外一个对象进行初始化;

如果这样的话

point p2(p1); 第三条

f(p2); 第一条

p2 = g(); 第二条

应该要三次调用拷贝构造函数才对然而vs编译的只调用了两次,cb编译的应该也只调用了两次(第一次和第三次),如果第三次确实正确调用了的话应该会显示提示信息才对,但并没有显示orz

[查看全文]