【问题标题】:Calls for constructors and destructors do not match the number of objects created [closed]对构造函数和析构函数的调用与创建的对象数量不匹配[关闭]
【发布时间】:2021-09-23 08:30:58
【问题描述】:

这是我的代码:

#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 line1(10);

    Line line2 = line1; // This also calls copy constructor

    display(line1);
    display(line2);

    return 0;
}

谁能解释一下这个输出?

我无法理解重复打印。

输出:

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

【问题讨论】:

  • 我们已经从您之前的两个问题中删除了 C 标记,现在我们正在从这个问题中删除它。我们不是为了好玩。不要使用不相关的标签。您的代码显然不是 C。
  • 代码也很奇怪。当你有一个类时,为什么要使用数组来存储数据和元数据?没有意义。
  • 另外,您还没有解释不清楚的地方。有哪些细节不清楚?

标签: c++ class object pointers


【解决方案1】:

您程序中的事件顺序,为了更好地理解而分成小步骤,如下所示:

调用line1的构造函数:

Line line1(10); //Normal constructor allocating ptr

1.line1 复制到line2 并为此调用复制构造函数:

   Line line2 = line1; //Copy constructor allocating ptr.

2. 因为参数是按值传递给display(),所以它复制line1 以在函数中使用:

    display(line1); //Copy constructor allocating ptr.

3.然后它执行display(),之后它不再需要line1参数,它是line1的一个副本,所以它调用了它的析构函数:

//Length of line : 10
//Freeing memory!

4.同样,它复制了line2,因为你通过值将它传递给display(),如果你通过指针或引用传递它会有所不同:

   display(line2); //Copy constructor allocating ptr.

5. 执行 display 并再次调用所创建副本的析构函数:

//Length of line : 10
//Freeing memory!

6. 之后,它会在结束执行之前调用原始 line1line2 对象的析构函数:

//Freeing memory!
//Freeing memory!

如果通过引用传递对象,您可以观察到差异,

void display(Line &obj)

使用上述构造,您会看到少了两个复制构造函数,因此少了两个析构函数:

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

为此,理想情况下您将使用void display(const Line &amp;obj),因为您不打算更改对象,但是您需要将int getLength(void); 更改为int getLength(void) const;,因为您将使用const 引用.

【讨论】:

    【解决方案2】:

    我想你在调用 display 时被文案弄糊涂了。

    void display(Line obj) { // creates a copy of the argument
    

    试试看

    void display(Line const& obj) {  // creates a const reference to the argument
    

    别忘了让 get lenght const

    int getLength() const;
    int Line::getLength() const{
    

    因此您可以在 const Line 对象上调用 getLenth。

    【讨论】:

    • 它仍然失败。 getLength 需要是一个 const 函数
    • 所以让它成为常量?我认为你应该在提问之前尝试谷歌一段时间。
    • 考虑您的语言。评论不是由 OP 提出的。我想这是为了帮助改进这个答案
    • 对不起。
    猜你喜欢
    • 1970-01-01
    • 2017-09-20
    • 1970-01-01
    • 2013-09-24
    • 2018-07-06
    • 1970-01-01
    • 2019-07-25
    • 2010-10-08
    相关资源
    最近更新 更多