Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/160.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/http/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何不删除基类对象的副本?_C++ - Fatal编程技术网

C++ 如何不删除基类对象的副本?

C++ 如何不删除基类对象的副本?,c++,C++,我的问题是,当我使用继承类时,我的基类删除了2次(继承的副本也删除了)。是否有机会不复制基类?还是不删除呢 #include <iostream> using namespace std; class base { public: base() { cout << "*B"; } ~base() { cout << "~B"; } }; class restaurant : virtual public base {}; int main

我的问题是,当我使用继承类时,我的基类删除了2次(继承的副本也删除了)。是否有机会不复制基类?还是不删除呢

#include <iostream>

using namespace std;
class base {
public:
    base() { cout << "*B"; }
    ~base() { cout << "~B"; }
};

class restaurant : virtual public base {};

int main() {
    base* d1 = new base;
    restaurant restaurant;
    delete d1;
    return 0;
}
#包括
使用名称空间std;
阶级基础{
公众:

base(){cout您不是
delete
ing
restaurant
,但是您也没有
new
它;它是在自动存储(“堆栈”)中分配的,而不是在动态存储(“堆”)中分配的。自动存储中的对象在超出作用域时会调用其析构函数。这就是为什么在这种情况下仍会调用
餐厅
析构函数的原因

如果你写过:

restaurant *restaurant = new restaurant;

您将看到您期望的行为。当然,如果调用
new
而没有匹配的
delete
,您将泄漏对象,因此不建议这样做。

您没有
delete
ing
restaurant
,但您也没有
new
它;它是在自动存储(“堆栈”)中分配的,而不是动态存储(“堆”)。自动存储中的对象在超出范围时会调用其析构函数。这就是为什么在这种情况下仍会调用
析构函数的原因

如果你写过:

restaurant *restaurant = new restaurant;

您将看到您期望的行为。当然,如果调用
new
而没有匹配的
delete
,您将泄漏对象,因此不建议这样做。

输出是期望的输出。 我在你的主要功能代码中添加了注释

int main() {

    //Create base class object and constructor will be called
    //This object is allocated on heap
    base* d1 = new base;

    //Create derived class object
    //first constructor of base and then derived (if defined) will be called 
    //This object is allocated on stack
    restaurant restaurant;

    //Free memory and Call destructor of base class object
    delete d1;

    return 0;

    //After bracket, stack object will go out of scope and destructor will be called.
    //First derived (if defined) class destructor and then base class destructor.
}
要获得预期的输出:
*B*B~B

restaurant *restaurant = new restaurant;

但如果不删除它,则会在程序中产生内存泄漏。

输出为预期输出。 我在你的主要功能代码中添加了注释

int main() {

    //Create base class object and constructor will be called
    //This object is allocated on heap
    base* d1 = new base;

    //Create derived class object
    //first constructor of base and then derived (if defined) will be called 
    //This object is allocated on stack
    restaurant restaurant;

    //Free memory and Call destructor of base class object
    delete d1;

    return 0;

    //After bracket, stack object will go out of scope and destructor will be called.
    //First derived (if defined) class destructor and then base class destructor.
}
要获得预期的输出:
*B*B~B

restaurant *restaurant = new restaurant;

但如果不删除它,则会在程序中产生内存泄漏。

首先,具有自动存储的对象会在作用域的末尾自动删除。因此,声明
餐厅餐厅;
将构造餐厅,但也会在
主功能的末尾自动删除它

试试这个:

struct A {
    A() { std::cout << "A()"; }
    ~A() { std::cout << "~A()"; }
};

struct B : A {
    B() { std::cout << "B()"; }
    ~B() { std::cout << "~B()"; }
};

auto main() -> int {
    B b;
} // b destroyed here
它的行为就像一个堆栈。首先,构造基类,然后构造派生类。然后,它首先销毁派生类,最后销毁基类

<>这个行为对于大多数C++习语来说是非常重要的。 考虑这一点:

struct A {
    A() : arr(new int[3]{1, 2, 3}) {}
    ~A() { delete[] arr; }
    int* arr = nullptr;
};

struct B : A {
    B() {}
    ~B() {}
    auto stuff() -> int {
        return std::accumulate(arr, arr + 3, 0);
    }
};

auto main() -> int {
    B b;
    return b.stuff(); // returns 1 + 2 + 3
}
如果没有首先执行构造函数
A()
,会发生什么情况?数组将为null。这将很糟糕

还有…如果析构函数
~A()
没有执行会发生什么?那将是内存泄漏。那将非常糟糕


构造函数和析构函数有保证的执行和定义良好的顺序。这就是为什么不必调用
super()
~super()
在你们所有的构造函数和析构函数中。因为你们可能会忘记调用它。析构函数和构造函数并不是你们想忘记调用的东西,否则仅仅使用C中的自由函数是没有好处的。

首先,具有自动存储的对象会在作用域结束时自动删除。所以声明e> 餐厅餐厅;
将创建一个餐厅,但也将在
主功能的末尾自动删除该餐厅

试试这个:

struct A {
    A() { std::cout << "A()"; }
    ~A() { std::cout << "~A()"; }
};

struct B : A {
    B() { std::cout << "B()"; }
    ~B() { std::cout << "~B()"; }
};

auto main() -> int {
    B b;
} // b destroyed here
它的行为就像一个堆栈。首先,构造基类,然后构造派生类。然后,它首先销毁派生类,最后销毁基类

<>这个行为对于大多数C++习语来说是非常重要的。 考虑这一点:

struct A {
    A() : arr(new int[3]{1, 2, 3}) {}
    ~A() { delete[] arr; }
    int* arr = nullptr;
};

struct B : A {
    B() {}
    ~B() {}
    auto stuff() -> int {
        return std::accumulate(arr, arr + 3, 0);
    }
};

auto main() -> int {
    B b;
    return b.stuff(); // returns 1 + 2 + 3
}
如果没有首先执行构造函数
A()
,会发生什么情况?数组将为null。这将很糟糕

还有…如果析构函数
~A()
没有执行会发生什么?那将是内存泄漏。那将非常糟糕



构造函数和析构函数有保证的执行和定义良好的顺序。这就是为什么不必调用
super()
~super()
在所有构造函数和析构函数中。因为您可能会忘记调用它。析构函数和构造函数不是您想忘记调用的东西,否则只使用C中的自由函数没有任何好处。

在退出main期间删除对象。。但您确实删除了餐厅
此处-->
返回0;
。当函数在其作用域中存在时,所有局部变量都会被销毁。您似乎误解了对象生命周期的工作方式……当“restaurant”对象超出作用域时,它仍然会被删除,这就是第二个“~B”的位置来自。我明白了,所以没有机会不在控制台中显示它?事实上,当它正在删除时,它是可以的,但我不想在控制台中显示它…并且您的基类中缺少一个虚拟析构函数。当您尝试一个
base*b=new restaurant,
时,它会泄漏,即使您调用
delete b;
对象是d退出main时删除。但您确实删除了
restaurant
此处-->
返回0;
。当函数在其作用域中存在时,所有局部变量都会被销毁。您似乎误解了对象生命周期的工作方式……当“restaurant”对象超出作用域时,它仍会被删除,这就是您的第二个“~B”的位置来自。我明白了,所以没有机会不在控制台中显示它?事实上,当它正在删除时,它是可以的,但我不想在控制台中显示它…并且您的基类中缺少一个虚拟析构函数。当您尝试
base*b=新餐厅时,它会泄漏,
即使您调用
delete b;
最好在此上下文中使用“自动存储”而不是“堆栈”之类的词。@SergeyA提到这两个词当然没什么坏处,谢谢。好的,我照你说的做了,它正在工作,谢谢你。@VidelIchinose如果你不删除,你就有内存泄漏。试着不要这样做。我对这个答案投了反对票。它建议泄漏一个对象,这