8wDlpd.png
8wDFp9.png
8wDEOx.png
8wDMfH.png
8wDKte.png

为什么在 C++ 中复制构造函数应该通过引用接受其参数?

Bnteo Costa 1月前

21 0

为什么复制构造函数的参数必须通过引用传递?

为什么复制构造函数的参数必须通过引用传递?

帖子版权声明 1、本帖标题:为什么在 C++ 中复制构造函数应该通过引用接受其参数?
    本站网址:http://xjnalaquan.com/
2、本网站的资源部分来源于网络,如有侵权,请联系站长进行删除处理。
3、会员发帖仅代表会员个人观点,并不代表本站赞同其观点和对其真实性负责。
4、本站一律禁止以任何方式发布或转载任何违法的相关信息,访客发现请向站长举报
5、站长邮箱:yeweds@126.com 除非注明,本帖由Bnteo Costa在本站《oop》版块原创发布, 转载请注明出处!
最新回复 (0)
  • 因为如果不是通过引用,那么就是通过值。要做到这一点,您需要进行复制,然后调用复制构造函数。但要做到这一点,我们需要创建一个新值,因此我们调用复制构造函数,依此类推...

    (您将会有无限递归,因为“要制作副本,您需要制作副本”。)

  • @Barry 当编译器尝试通过调用 object o(other_object) 自行复制对象时,您通常会实现复制构造函数。但这仅在对象具有通过值或引用获取另一个对象的构造函数时才有效。您已经知道为什么通过值传递不起作用,因此唯一的方法是通过引用或 const 引用传递。如果您的“复制构造函数”将获取指向对象的指针,则编译器的代码必须是 object o(&other_object)。因此,从本质上讲,您编写了一个满足编译器和用户期望的构造函数。

  • 我的编译器指出的另一个很好的理由是,如果你有一个具有纯虚函数的基类,则无法通过值初始化此变量

  • 引用传递的替代方法是值传递。值传递实际上是复制传递。需要使用复制构造函数进行复制。

    如果只是为了调用复制构造函数而必须进行复制,那么这将是一个难题。

    (我认为无限递归会发生在编译器中,而你实际上永远不会得到这样的程序。)

    除了 合理的 原因之外,标准§12.8/3也禁止这样做:

    如果类 X 的构造函数的第一个参数为类型(可以是 cv 限定的)X,并且没有其他参数,或者所有其他参数都有默认参数,则该类构造函数的声明格式不正确。

  • 编译器可以愉快地生成无限递归;我怀疑这不是特殊情况。但是,如果您使用非引用参数声明复制构造函数,则程序格式不正确。所以您说得对,它不应该编译。

  • @Dennis:我的意思是,如果你尝试编译这样的程序,编译器会在尝试生成代码时卡住。它不会生成递归函数,因为难题发生在函数调用之前,在调用者中。

  • 不管怎样,无论你是否尝试使用它,程序都是不规范的。仅仅定义构造函数就足以让编译器对你大喊大叫。

  • Dima 1月前 0 只看Ta
    引用 9

    每当您调用一个函数(例如:int f(car c))时,该函数采用除内置数据类型(此处为 car)之外的参数,要求将调用者提供的实际对象复制到被调用函数参数中的变量中。
    例子:

    car carobj; f(carobj);

    即复制 carobj c .

    carobj 需要复制到 c 函数中的 f .

    为了实现复制,需要调用复制构造函数。

    在这种情况下,函数 f 使用按值传递进行调用,或者换句话说,函数 f 被声明为按值传递。

    如果函数 f 通过引用传递,那么它的声明是 int f(car &c);

    在这种情况下,
    car carobj; f(carobj);

    不需要复制构造函数。

    在这种情况下, c 成为 carobj .

    使用上述两种场景,为了您的清楚起见,我将它们总结为:

    1. p10

    2. p11

    现在的问题是为什么需要通过引用传递。如果复制构造函数接受引用,则接收变量将成为所提供对象的别名。因此,不需要复制构造函数(在这种情况下,调用自身)将调用者提供的对象中的值复制到参数列表中的复制构造函数的变量中。

    否则,如果复制构造函数将调用者提供的对象作为值,即按值传递,那么它需要给定对象的复制构造函数;因此,为了将调用者提供的对象放入我们的函数本身(在本例中为复制构造函数),我们需要调用复制构造函数,这只不过是在函数声明期间调用相同的函数。

    这就是将引用传递给复制构造函数的原因。

  • 引用 10

    虽然你说得对,但已经有四个答案解释了这一点,而且解释得更清楚。我不明白你为什么认为这个问题的第五个答案会有帮助。

  • 引用 11

    有必要将对象作为引用传递而不是按值传递,因为如果按值传递,则其副本是使用复制构造函数构造的。这意味着复制构造函数将调用自身进行复制。此过程将持续,直到编译器内存不足。

  • 将对象作为引用传递非常重要。如果将对象作为值传递给复制构造函数,则其复制构造函数将调用自身,将实际参数复制到形式参数。因此将启动对复制构造函数的无限调用链。此过程将持续进行,直到系统内存耗尽。

    因此,在复制构造函数中,参数应始终作为引用传递。

  • 如果不是通过引用传递,那么它将通过值传递。如果参数是通过值传递的,它的复制构造函数将调用自身将实际参数复制到形式参数。这个过程将一直持续到系统内存不足为止。所以,我们应该通过引用传递它,这样就不会调用复制构造函数。

  • 复制构造函数定义了复制的含义,因此如果我们只传递一个对象(我们将传递该对象的副本)但要创建副本,我们将需要一个复制构造函数,因此它会导致无限递归。

    因此,复制构造函数必须有一个引用作为参数。

  • 引用 15

    所有答案都是正确的,但我想知道这些答案是否能帮助像我这样通过示例学习的初学者。所以,这里有一个例子。

    以此代码为例:

    #include<iostream>
    #include<cstring>
    using namespace std;
    
    class String
    {
    private:
        char *s;
        int size;
    public:
        String(const char *str)
        {
    
            size=strlen(str);
            s=new char[size+1];
            strcpy(s,str);
        }
        ~String()
        {
            delete[] s;
        }
    
        String(const String& old_str)
        {
            size=old_str.size;
            s=new char[size+1];
            strcpy(s,old_str.s);
    
        }
        void print()
        {
            cout<<s<<endl;
        }
        void change(const char *str)
        {
            delete [] s;
            size=strlen(str);
            s=new char[size+1];
            strcpy(s,str);
        }
    };
    int main()
    {
        String str1("Hello World");
        String str2=str1;
    
        str1.print();
        str2.print();
    
        str2.change("Namaste");
        str1.print();
        str2.print();
        return 0;
    }
    

    这是复制构造函数:

    String(const String& old_str)
            {
                size=old_str.size;
                s=new char[size+1];
                strcpy(s,old_str.s);
        
            }
    

    想象一下我们不通过引用传递。即:

    String(const String old_str)
            {
                size=old_str.size;
                s=new char[size+1];
                strcpy(s,old_str.s);
        
            }
    

    看看 int main() 函数。

    String str2=str1
    

    再次查看复制构造函数(无引用)。

    String(const String old_str)
    

    这意味着:

    String old_str=str1
    

    它基本上和 main() 函数中写的内容相同。因此,它再次调用复制构造函数。在 C++ 中调用复制构造函数的规则是当您遇到以下情况时:

    ABC a;
    ABC b=a;
    

    我希望这会有所帮助。

返回
作者最近主题: