dev_c++ 复制构造函数

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了dev_c++ 复制构造函数相关的知识,希望对你有一定的参考价值。

下面这段代码在VC++中可以编译运行
在Dev-c++为什么不能编译运行?
#include <iostream>
using namespace std;
class A

public:
A(int i)cout<<"构造函数执行\n";x=i;
A(A&a)cout<<"复制构造函数创建对象\n";x=a.x;
~A()cout<<"析构函数\n";
int get()return x;
private:
int x;
;
A func()

cout<< " 跳转到func函数中"<<endl;
A a(23);
cout<<"a 的地址"<<&a<<endl;
return a;

int main()

A&r=&func();
cout<<r->get()<<endl;
cout<<"a 的地址"<<r<<endl;
system ("pause");
return 0;



如果在func函数前面加上引用,A &func() devc++就可以编译了。
可是a出去不是空引用么?怎么会得到a的值呢?
A&r=func(); //这前面没有&
cout<<r.get()<<endl; //这里不是指针 用的是"."
cout<<"a 的地址"<<&r<<endl; //这里是&r
system ("pause");
return 0;

这代码看着像是范磊老师的《C++全方位学习》里的代码,这是一本好书,但作者使用了已经被淘汰的VC++6.0,书中的代码BUG也是与此有关。我来回答你的问题,很简单,你的代码需要修改为:
#include <iostream>
using namespace std;
class A

public:
A(int i)cout<<"构造函数执行\n";x=i;
A(A&a)cout<<"复制构造函数创建对象\n";x=a.x;
~A()cout<<"析构函数\n";
int get()constreturn x; //因为第22行代码A&r=&func();改为了const A&r=func();此处必须加const。
private:
int x;
;
A func()

cout<< " 跳转到func函数中"<<endl;
A a(23);
cout<<"a 的地址"<<&a<<endl;
return a;

int main()

const A&r=func(); //r是一个类A的引用,func()函数返回的是一个类A的对象,不是指针,func()函数前不要&。引用必须和对象绑定,不能和数值或计算式绑定,否则要加const。(早期的编译器如:VC++6.0可以写成A &r=func(),现在的编译器都不支持)
cout<<r.get()<<endl;//r不是指针,要改成r.get()
cout<<"a 的地址"<<&r<<endl;//r是一个类A的引用,输出r地址应改为&r
system ("pause");
return 0;

最后回答你func()函数返回的是一个临时对象,为什么“cout<<r.get()<<endl;”还能得到23?
因为对于引用而言,如果引用的是一个临时变量,那么这个临时变量的生存期会不小于这个引用的生存期(可参见C++标准[class.temporary])。也就是说,直到main函数结束时,引用r的生存期才结束,所引用的临时变量的生存期也才结束。
需要特别说明的是以上代码在Dev c++和vs2017的运行结果是不一样的。vs2017会调用复制构造函数,func()函数返回的是对象a的副本;Dev c++不会调用复制构造函数,func()函数返回的是对象a本身。
参考技术A 稍微修改了你的代码,得到了正确的结果

#include <iostream>
using namespace std;
class A

public:
A(int i)cout<<"构造函数执行\n";x=i;
A(A&a)cout<<"复制构造函数创建对象\n";x=a.x;
~A()cout<<"析构函数\n";
int get()return x;
private:
int x;
;
A* func()

cout<< " 跳转到func函数中"<<endl;
A* a = new A(23);
cout<<"a 的地址"<<&a<<endl;
return a;

int main()

A* r = func();
cout<<r->get()<<endl;
cout<<"a 的地址"<<r<<endl;
system ("pause");
return 0;


按照你的改动,我的dev-cpp也还是不能编译,感觉这么改正规一点,函数返回值返回一个指针才能在后用执行->运算符吧

补充:

这里可能是调用了隐式的拷贝构造函数,因为你显式定义的拷贝构造函数不能完成A& r = func();这一句的拷贝构造。因此编译器为你隐式的定义了属于A& r = func();这种调用方法的拷贝构造函数。

另外a确实在函数局部被析构了,但这发生在return语句之后,return语句已经将a返回给了A& r,r.get()依然能返回23本回答被提问者采纳

C++中复制构造函数被调用的三种情况

C++中的构造函数

c++中的构造函数分为构造函数,和复制构造函数,相比于构造函数,复制构造函数使用更加方便,快捷。构造函数可以有多个,二复制构造函数只能有一个,因为复制构造函数的参数
只能是当前类的一个对象,参数表是固定的,无法重载,若用户没有定义自己的辅助构造函数,系统会自动生成一个复制构造函数,其作用是将参数的之赋予当前的对象.若用户自己定义了复制构造函数,系统则不会生成默认复制构造函数。用户自己定义的复制构造函数功能可以自己构造,不一定执行复制的功能。

复制构造函数同构造函数的功能大体相同·,却又有不同之处,下面介绍复制构造函数在3中情况下的调用
1.当用一个对象去初始化同类的另一个对象时,会引发复制构造函数的调用

以下两条语句都会导致复制构造函数的调用

     Complex c1(c2);
     Complex c1=c2;

这两条语句时等价的,其中第二句是初始化语句,不是赋值语句

下面这一条语句不会调用复制构造函数

     Complex c1,c2;
     c1=c2;



2.作为形参的对象,使用复制构造函数初始化的
以下语句可以证明


    #include<iostream>
    using namespace std;
    class A
     public:
        A();//构造函数
         A(A&a)//复制构造函数
        
            cout<<"Copy constructer called"<<endl;
        
      ;
      void Func(A a)//普通函数
     

     
     int main()
      
      A b;
      Func(b);//此语句相当于是将b复制给Func(a)中的a,导致调用复制构造函数
      retur 0;

      

程序运行截图
技术图片

3.如果函数返回的是类A的对象,那么函数返回时,类A的复制构造函数会被调用
程序如下

     #include<iostream>
     using namespace std;

     class A
     public:
       int v;
       A(int i)
           v=i;
        ;//构造函数
        A(A&a)//复制构造函数
        
            cout<<"Copy constructer called"<<endl;
         
      ;
       A a(4);
       A Func()//普通函数
       

          return a;
       
        int main()
        
        cout<<Func().v<<endl;//此语句中的Func()是一个类A的对象,但是不是a,只是用a初始化。
        return 0;

      

技术图片

以上三种情况是比较常见的复制构造函数被调用的例子

欢迎讨论,斧正

以上是关于dev_c++ 复制构造函数的主要内容,如果未能解决你的问题,请参考以下文章

复制构造函数(拷贝构造函数)

C++中复制构造函数被调用的三种情况

C++——构造函数析构函数以及复制构造函数

为啥我们需要复制构造函数以及何时应该在 java 中使用复制构造函数

复制构造函数的运用

为啥标准不将模板构造函数视为复制构造函数?