首页 新闻 搜索 专区 学院

关于c++复制构造函数的问题!!!

0
悬赏园豆:20 [已解决问题] 解决于 2012-08-03 09:02

我知道c++编译器会生成合成复制构造函数,我想提出问题是:当程序员定义了复制构造函数,那么编译器还会生成合成复制构造函数吗?如果此时编译器会生成合成复制构造函数,那么在程序运行的时候,只运行其中一个,还是像析构函数一样先运行程序员编写的复制构造函数,再运行合成复制构造函数?

我做了如下测试:

 

测试代码
 1 #include<iostream>
 2 using std::cout ;
 3 using std::endl ;
 4 
 5 class copyTest
 6 {
 7 public:
 8     copyTest(int i=0):val(i){}
 9     copyTest(const copyTest& ct)
10     {
11         cout<<"调用我了!"<<endl;
12     }
13     void fntest(copyTest ct)
14     {
15         cout<<"函数调用"<<ct.val <<endl;
16     }
17     int val;
18 };
19 int main()
20 {
21     int i=5;
22     cout<<"复制初始化测试:隐式调用构造函数"<<endl;
23     copyTest test1=i;
24     cout<<test1.val <<endl;
25     cout<<"复制初始化测试:显示调用构造函数"<<endl;
26     copyTest test3(5);
27     copyTest test4=test3;
28     cout<<test4.val <<endl;
29     cout<<"复制实参测试:"<<endl;
30     copyTest test2;
31     test2.fntest (test1);
32 
33     getchar();
34 }

 

测试结果如下:

由以上测试结果可以看出:当隐式调用构造函数来复制初始化时,好像没有调用程序员编写的复制构造函数,但结果是正确的;其他两种都进入了程序员编写的复制构造函数,结果错误。这样测试结果让我得不出我想要的结论。求帮助!!!!

探索超越的主页 探索超越 | 初学一级 | 园豆:184
提问于:2012-08-02 09:02
< >
分享
最佳答案
0

copyTest(const copyTest& ct)
{
   cout<<"调用我了!"<<endl;
}

写错了,比如可以写成这样: copyTest(const copyTest& ct) : val(ct.val)

收获园豆:20
Launcher | 高人七级 |园豆:45045 | 2012-08-02 09:19

我是故意写错的,就是想看看在我编写的复制构造函数不做任何工作的情况下,会出现什么情况。但我的测试程序显示结果是:第一种情况居然结果对了,其余两种都错了。你能回答我的提问和我的程序为什么会出现这样的结果吗?

探索超越 | 园豆:184 (初学一级) | 2012-08-02 13:34

@探索超越: 第一个,是因为你有此构造函数: copyTest(int i=0):val(i){} ,所以右操作数为int时,它会匹配该构造函数。第二个是因为你的copyTest(const copyTest& ct){}空操作,随意test4=test3的时候,没有赋值。第三个还是因为你的此构造函数:copyTest(int i=0):,这里你提供了0 的缺省值。

Launcher | 园豆:45045 (高人七级) | 2012-08-02 14:28

@程序猿.码农: 对于第一个,我还是不太能认同你,我读的书是c++primer,它里面有这样几句话:

上面用红线圈住的话:根据上面的意思,我的理解是:第一步:先调用copyTest(int i=0)这个构造函数生成临时对象,然后再调用copyTest类的复制构造函数来进行初始化。关键是结果中没有显示出调用复制构造函数,莫非调用了编译器合成复制构造函数?你把qq号给我说下方便交流,我的qq:820771914,只要问题解决,园豆还是你的。

探索超越 | 园豆:184 (初学一级) | 2012-08-02 16:34

@探索超越: 你的 int 是基本数据类型,而 string 不是,所以编译器需要先把你写的"sdfsdf-sdfsd-sdfsd"创建为一个临时的 string 类型,然后才能调用 string 的拷贝构造函数,但这并不能说明使用任何实参都会创建一个临时的对象后再调用拷贝构造函数(而且通过汇编代码来看,编译器也不一定非要构造这个临时的字符串对象)。

我们来好好理解下“只有指定单个实参或显示创建一个临时对象用于复制时,才使用复制初始化”,拆分成两句:

1,指定单个实参时使用复制初始化的对应代码是这样:

string str = "sdfdsf-sdfsd-sdfsf"; // "sdfdsf-sdfsd-sdfsf" 就是实参,此处需要隐式的创建一个 string 对象,但并不代表所有编译器都会这么做,或者说一直这么做。

这段代码可以这样:

string str1 = "sdfdsf-sdfsd-sdfsf";

string str2 = str1; // str1 就是实参

2,显示创建一个临时对象用于复制时,使用复制初始化的对应代码是这样:

string str = string(); // string() 是显示创建一个临时的对象。

这段代码可以这样来看:

string str1 = string();

string str2 = str1;

同 1 的结构一样。

再来看 std::string 的定义,MBCS的定义为:basic_string<char, char_traits<char>, allocator<char> >,它的拷贝构造函数是:basic_string(const _Myt& _Right),而 _Myt 是basic_stringchar, char_traits<char>, allocator<char>> 类型,所以会需要先创建一个 string  临时对象,因为 string 没有可以接受“字符串”类型的构造函数,只有编译器能识别出来。

Launcher | 园豆:45045 (高人七级) | 2012-08-02 17:55
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册