简体   繁体   English

为什么在这个例子中调用了复制构造函数?

[英]Why was copy constructor called in this example?

I am very new to C++ and I don't understand why the copy constructor was called in the following code: 我是C ++的新手,我不明白为什么在下面的代码中调用了复制构造函数:

 #include <iostream>

    using namespace std;

    class Line

{
   public:
      int getLength( void );
      Line( int len );             // simple constructor
      Line( const Line &obj);  // copy constructor
      ~Line();                     // destructor

   private:
      int *ptr;
};

// Member functions definitions including constructor
Line::Line(int len)
{
    cout << "Normal constructor allocating ptr" << endl;
    // allocate memory for the pointer;
    ptr = new int;
    *ptr = len;
}

Line::Line(const Line &obj)
{
    cout << "Copy constructor allocating ptr." << endl;
    ptr = new int;
   *ptr = *obj.ptr; // copy the value
}

Line::~Line(void)
{
    cout << "Freeing memory!" << endl;
    delete ptr;
}
int Line::getLength( void )
{
    return *ptr;
}

void display(Line obj)
{
   cout << "Length of line : " << obj.getLength() <<endl;
}

// Main function for the program
int main( )
{
   Line line(10);

   display(line);

   return 0;
}

And when it runs: 当它运行时:

Normal constructor allocating ptr
Copy constructor allocating ptr.
Length of line : 10
Freeing memory!
Freeing memory!

Why does it construct an other Line object after the first one with the simple constructor? 为什么在第一个具有简单构造函数的对象之后构造另一个Line对象?

Thanks! 谢谢!

because you are passing Line as value 因为您将Line作为值传递

void display(Line obj)
{
   cout << "Length of line : " << obj.getLength() <<endl;
}

You should pass it as constant reference, which is faster (and display shoud be a constant method so constant objects can call it). 你应该将它作为常量引用传递,这更快(并且display应该是一个常量方法,因此常量对象可以调用它)。

void display(const Line &obj) const
{
   cout << "Length of line : " << obj.getLength() <<endl;
}

(provided that you change to int getLength( void ) const; ) (假设您更改为int getLength( void ) const;

And in your case, think of redefining assignment operator 在您的情况下,考虑重新定义赋值运算符

Line &operator=(const Line &other);

or affecting a line in another will copy pointer data and will crash on your second object deletion since memory will be freed twice. 或影响另一行中的一行将复制指针数据,并将在第二个对象删除时崩溃,因为内存将被释放两次。

If you want to make sure that default copy constructor / assignment operator cannot be called, just declare them in your private part: 如果要确保无法调用默认的复制构造函数/赋值运算符,只需在私有部分中声明它们:

private:
  Line &operator=(const Line &other);
  Line(const Line &other);

code trying to use them won't compile. 试图使用它们的代码将无法编译。

Your display function takes a Line by value - meaning the function gets its own copy . 您的display功能采用Line by值 - 意味着该函数获得自己的副本 If you don't want that, pass by (const) reference or pointer instead. 如果你不想这样,请改为传递(const)引用或指针。

The answer is here: 答案在这里:

void display(Line obj) { ...

The argument of the function obj is passed by value . 函数obj的参数是通过值传递的

So when the function is called a copy of the argument passed by the caller function is done. 因此,当调用函数时,调用函数传递的参数的副本就完成了。

In order to give you a trivial explanation, imagine: 为了给你一个简单的解释,想象一下:

function:main (caller) -> 
make a copy of line ->
call the function display (callee) which is going to use the copy made by caller.

That policy is used in various case, for example : 该政策用于各种情况, 例如

  • To be sure that the callee function will does any effect ( side-effect ) on the variables of the caller. 确保被调用函数对调用者的变量产生任何影响( 副作用 )。
  • When the callee function will perform a copy of the object, so you can avoid to make a copy inside the body function. 当被调用函数执行对象的副本时,可以避免在body函数内部进行复制。

Because passing an argument by value will perform a copy of the argument itself, it is preferable using argument passed by reference . 因为按值传递参数将执行参数本身的副本 ,所以最好使用通过引用传递的参数

This is an example: 这是一个例子:

void display(Line& obj) { ...

In that case it will not performed a copy of the object but the argument obj will be a reference (like a pointer) to the argument passed by the caller function. 在这种情况下,它不会执行对象的副本,但参数obj将是调用者函数传递的参数的引用 (如指针)。

In conclusion, passing by reference allows to callee function side effect , in other words the callee function can modify variables " owned " by caller function. 总之,通过引用传递允许被调用函数的副作用 ,换句话说,被调用函数可以修改由调用函数“ 拥有 ”的变量。

Copy constructors are called in following cases: 在以下情况下调用复制构造函数:

(a) when a function returns an object of that class by value (a)当函数按值返回该类的对象时

(b) when the object of that class is passed by value as an argument to a function (b)当该类的对象通过值作为函数的参数传递时

(c) when you construct an object based on another object of the same class (c)当你根据同一个类的另一个对象构造一个对象时

(d) When compiler generates a temporary object and is initialized with a class object. (d)编译器生成临时对象并使用类对象初始化时。

And in your code you are passing the object of that clas by value as an argument to a function Hope this Helps 并且在您的代码中,您通过值将该clas的对象作为参数传递给函数Hope this Helps

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM