javascript

java

python

c#

android

node.js

c++

reactjs

php

html

jquery

css

.net

ios

git

ruby-on-rails

sql

c

string

ruby

从C ++中的析构函数中恢复对象?

免责声明:我知道这是一个糟糕的设计,我只是出于好奇而提出这个问题,以便尝试获得有关析构函数在C ++中如何工作的更深入的知识。

在C#中,可以写:2749286428323623611648在一个类的析构函数中(请参见下面的编辑),这意味着即使在析构函数调用完成之后,该对象仍将在内存中保持活动状态。

C ++的设计是否允许类似于上述C#算法从析构函数中恢复对象?

编辑:正如下面的回答所指出,GC.ReRegisterForFinalize()与该问题的关系比GC.KeepAlive(this)更紧密。

trans by 2020-02-15T23:05:59Z

在C ++中调用析构函数和构造函数的顺序是什么

在C ++中调用析构函数和构造函数的顺序是什么? 使用一些基类和派生类的示例

trans by 2020-02-14T16:45:23Z

构造函数-C ++默认构造函数

例如,当我不声明constructor时,编译器将为我提供default constructor,它没有参数也没有定义(正文),因此将不采取任何措施。

如果我现在不声明default constructor,则编译器将为我提供default destructor没有定义(body),因此,我认为不采取任何措施。

因此,例如,如果我完成了一个对象,那么default constructor不会重新分配该对象使用的(空闲)内存吗? 如果没有,我们为什么要得到它?

并且,也许相同的问题也适用于default constructor。如果它什么也不做,为什么默认情况下会为我们创建它?

谢谢。

trans by 2020-02-14T10:57:42Z

为什么我们需要使用虚拟〜A()= default; 而不是C ++ 11中的虚拟〜A(){}?

在Stack Overflow帖子中,检查C ++ 11中的对象类型,我有以下评论:

在C ++ 11中,您实际上将要执行virtual ~A() = default;否则,您将失去隐含的move构造函数。

virtual ~A() = default;是做什么用的? virtual ~A() {}为何隐式移动构造函数会丢失?

trans by 2020-02-08T19:13:24Z

析构函数可以递归吗?

这个程序定义明确吗?如果不正确,为什么呢?

#include <iostream>
#include <new>
struct X {
    int cnt;
    X (int i) : cnt(i) {}
    ~X() {  
            std::cout << "destructor called, cnt=" << cnt << std::endl;
            if ( cnt-- > 0 )
                this->X::~X(); // explicit recursive call to dtor
    }
};
int main()
{   
    char* buf = new char[sizeof(X)];
    X* p = new(buf) X(7);
    p->X::~X();  // explicit call to dtor
    delete[] buf;
}

我的推理:尽管两次调用析构函数是未定义的行为,但根据12.4 / 14,它的确切含义是:

如果行为是不确定的   为对象调用析构函数   生命已经结束

似乎并不禁止递归调用。 在执行对象的析构函数时,对象的生存期尚未结束,因此再次调用该析构函数不是UB。 另一方面,12.4 / 6表示:

执行尸体后   X类的析构函数调用   X的直接成员的析构函数,   X直接基地的破坏者   类[...]

这意味着在递归调用析构函数后,所有成员和基类析构函数都将被调用,而返回到先前的递归级别时再次调用它们将是UB。 因此,没有基础并且只有POD成员的类可以具有没有UB的递归析构函数。 我对吗?

trans by 2020-02-07T13:08:57Z

为什么没有在异常上调用析构函数?

我希望在该程序中调用cl /EHa my.cpp,但事实并非如此:

#include <iostream>

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

void f() {
  A a;
  throw "spam";
}

int main() { f(); }

但是,如果我将最后一行更改为

int main() try { f(); } catch (...) { throw; }

然后调用cl /EHa my.cpp

我正在从Visual Studio 2005中使用“ Microsoft(R)32位C / C ++为80x86优化编译器版本14.00.50727.762版本”。命令行为cl /EHa my.cpp

编译器像往常一样正确吗? 标准对此事怎么说?

trans by 2020-02-03T14:42:26Z

析构函数-何时在PHP中不调用__destruct?

class MyDestructableClass {
   function __construct() {
       print "\nIn constructor\n";
       $this->name = "MyDestructableClass";
   }

   function __destruct() {
       print "\nDestroying " . $this->name . "\n";
   }
}

$obj = new MyDestructableClass();

当上面的脚本在复杂的环境中时,exit不会被调用exit,但是我无法轻松地重现它。有人注意到吗?

编辑

我将在此处发布整个内容,这是symfony的测试环境,这意味着如果您熟悉框架,则可以轻松地重现它:

require_once dirname(__FILE__).'/../bootstrap/Doctrine.php';


$profiler = new Doctrine_Connection_Profiler();

$conn = Doctrine_Manager::connection();
$conn->setListener($profiler);

$t = new lime_test(0, new lime_output_color());

class MyDestructableClass {
   function __construct() {
       print "\nIn constructor\n";
       $this->name = "MyDestructableClass";
   }

   function __destruct() {
       print "\nDestroying " . $this->name . "\n";
   }
}

$obj = new MyDestructableClass();
$news = new News();

$news->setUrl('http://test');
$news->setHash('http://test');
$news->setTitle('http://test');
$news->setSummarize('http://test');
$news->setAccountId(1);
$news->setCategoryId(1);
$news->setThumbnail('http://test');
$news->setCreatedAt(date('Y-m-d H:i:s',time()));
$news->setUpdatedAt(date('Y-m-d H:i:s',time()));
$news->save();
exit();
trans by 2020-02-03T03:05:16Z

c-如何查询pthread是否仍在运行?

在我的析构函数中,我想干净地破坏线程。

我的目标是等待线程完成执行,然后销毁线程。

我发现有关查询pthread状态的唯一信息是pthread_attr_setdetachstate,但这只能告诉您线程是否为:

  • PTHREAD_CREATE_DETACHED
  • PTHREAD_CREATE_JOINABLE

两者都与线程是否仍在运行无关。

如何查询pthread是否仍在运行?

trans by 2020-02-02T21:05:01Z

C ++ 11-C ++局部变量销毁ord

在C ++(11)中是否有定义的顺序来分配局部变量?简而言之:在同一范围内,两个局部变量的析构函数的副作用将以何种顺序显现?

例如。:

struct X{
  ~X(){/*do something*/}
}

int main(){
   X x1;
   X x2;
   return 0;
}

是在main返回时首先销毁x1x2还是在C ++ 11中未定义顺序?

trans by 2020-01-29T22:35:05Z

C ++是否为全局和类静态变量调用析构函数?

在我的示例程序中,看起来在两种情况下都确实调用了析构函数。 在什么时候将其称为全局和类静态变量的析构函数,因为它们应在程序堆栈的数据部分中分配?

trans by 2020-01-29T08:02:00Z

您是否需要在析构函数中删除事件处理程序?

我使用一些ppmmEventHandler,它们在运行时在应用程序中创建和销毁(通过创建和关闭内部带有这些控件的子窗口)。
它是WPF用户控件,继承自System.Windows.Controls.UserControl。没有Dispose()我可以覆盖的方法。
PPMMSingleton,寿命与我的应用程序相同。
现在在我的(WPF)UserControl的构造函数中,添加一个事件处理程序:

public MyControl()
{
    InitializeComponent();

    // hook up to an event
    PPMM.FactorChanged += new ppmmEventHandler(PPMM_FactorChanged);
}

我习惯在析构函数中删除此类事件处理程序:

~MyControl()
{
    // hook off of the event
    PPMM.FactorChanged -= new ppmmEventHandler(PPMM_FactorChanged);
}

今天,我偶然发现了这一点,并想知道:

1)这是必要的吗? 还是由GC负责?

2)这还行吗? 还是我必须存储新创建的ppmmEventHandler

期待您的回答。

trans by 2020-01-26T09:23:03Z

可以自动将默认析构函数生成为虚拟析构函数吗?

可以将默认析构函数自动生成为虚拟析构函数吗?

如果我定义基类但没有默认析构函数,那么是否有默认的虚拟析构函数自动生成的?

trans by 2020-01-04T10:57:53Z

C ++构造函数/析构函数继承

编辑:答案摘要

在下面,B是A的子类。

这是一个术语问题; ctor和dtor不会继承,因为B的ctor / dtor不会从A的接口借用。 一个类至少具有一个构造函数,并且恰好具有一个析构函数。

  • 构造函数:
    • B不从A继承构造函数;
    • 除非B的ctor显式调用A的ctor之一,否则A的默认ctor将在B的ctor主体之前自动调用(这种想法是A需要在创建B之前被初始化)。
  • 析构函数:
    • B不继承A的dtor;
    • 退出后,B的析构函数将自动调用A的析构函数。

致谢:我要特别感谢Oli Charlesworth和Kos的回答,我将Kos的回答作为解决方案,因为这是我最了解的解决方案。


原始邮件

当您在Google上搜索“ C ++析构函数继承site:stackoverflow.com”时,当前发现以下帖子:

  1. 构造函数和析构函数继承:信誉超过30k的两个用户说它是继承的,不是
  2. 虚拟析构函数是否被继承?:这里没有提到任何指向析构函数不被继承的东西
  3. C ++中的析构函数和继承?:注释似乎表明析构函数是继承的

问题1:从实践中我还知道,如果不为派生类显式定义构造函数,就无法使用与父构造函数相同的原型初始化派生对象。


即使从帖子中可以很清楚地看出析构函数似乎是继承的,但我仍然感到困惑,因为拥有32k信誉的用户会说没有。 我写了一个小例子来阐明每个人的想法:

#include <cstdio>

/******************************/

// Base class
struct A
{
    A() { printf( "\tInstance counter = %d (ctor)\n", ++instance_counter ); }
    ~A() { printf( "\tInstance counter = %d (dtor)\n", --instance_counter ); }

    static int instance_counter;
};

// Inherited class with default ctor/dtor
class B : public A {};

// Inherited class with defined ctor/dtor
struct C : public A
{
    C() { printf("\tC says hi!\n"); }
    ~C() { printf("\tC says bye!\n"); }
};

/******************************/

// Initialize counter
int A::instance_counter = 0;

/******************************/

// A few tests
int main()
{
    printf("Create A\n"); A a;
    printf("Delete A\n"); a.~A();

    printf("Create B\n"); B b;
    printf("Delete B\n"); b.~B();

    printf("Create new B stored as A*\n"); A *a_ptr = new B();
    printf("Delete previous pointer\n"); delete a_ptr;

    printf("Create C\n"); C c;
    printf("Delete C\n"); c.~C();

}

这是输出(与g ++ 4.4.3编译):

Create A
    Instance counter = 1 (ctor)
Delete A
    Instance counter = 0 (dtor)
Create B
    Instance counter = 1 (ctor)
Delete B
    Instance counter = 0 (dtor)
Create new B stored as A*
    Instance counter = 1 (ctor)
Delete previous pointer
    Instance counter = 0 (dtor)
Create C
    Instance counter = 1 (ctor)
    C says hi!
Delete C
    C says bye!
    Instance counter = 0 (dtor)  // We exit main() now
    C says bye! 
    Instance counter = -1 (dtor)
    Instance counter = -2 (dtor)
    Instance counter = -3 (dtor)

Q2:有人认为它不是遗传的,请解释一下吗?

问题3:那么当您使用输入调用子类的构造函数时会发生什么? 是否也调用了超类的“空构造函数”?

trans by 2019-12-31T18:45:33Z

动态分配对象数组

这是一个初学者的问题,但是我很长一段时间没有做C ++,所以这里...

我有一个包含动态分配的数组的类,例如

class A
{
    int* myArray;
    A()
    {
        myArray = 0;
    }
    A(int size)
    {
        myArray = new int[size];
    }
    ~A()
    {
        // Note that as per MikeB's helpful style critique, no need to check against 0.
        delete [] myArray;
    }
}

但是,现在我想为这些类创建一个动态分配的数组。 这是我当前的代码:

A* arrayOfAs = new A[5];
for (int i = 0; i < 5; ++i)
{
    arrayOfAs[i] = A(3);
}

但是,这非常可怕。 因为创建的新vector对象(使用A调用)在A*循环迭代完成时被破坏,所以这意味着A实例的内部myArray实例将获得delete []-ed。

所以我认为我的语法一定很错误吗? 我猜想有一些似乎过大的修补程序,我希望避免:

  • vector创建副本构造函数。
  • 使用vectorA,所以我不必担心所有这些。
  • 不是让vector对象是A对象的数组,而是让它成为A*指针的数组。

我认为这只是一些初学者的事情,在尝试动态分配具有内部动态分配的事物数组时,确实有一种语法有效。

(此外,对样式的评论表示赞赏,因为自从我使用C ++已经有一段时间了。)

面向将来的观众的更新:以下所有答案确实很有帮助。 由于示例代码和有用的“ 4则规则”,Martin被接受了,但我确实建议阅读所有内容。 有些是关于错误之处的简洁明了的陈述,有些则正确指出了2674760767953953699840s如何以及为什么是一个不错的选择。

trans by 2019-12-26T13:11:56Z

c ++-内置类型(int,char等的析构函数)

在C ++中,以下代码给出了编译器错误:

void destruct1 (int * item)
{
  item->~int();
}

这段代码几乎相同,我只是将int定义为另一种类型,并且发生了一些魔术:

typedef int myint;

void destruct2 (myint * item)
{
  item->~myint();
}

第二个代码为什么起作用? 一个int是否仅仅因为已经被类型定义而得到了析构函数?

万一您想知道为什么要这样做:来自重构C ++代码。 我们正在删除标准堆,并用自制池替换它。 这就要求我们调用“ placement-new”和“析构函数”。 我知道为原始类型调用析构函数是没有用的,但是我们还是希望在代码中使用析构函数,以防以后我们用实类替换POD。

发现裸int无效,而typedefed的无效,这真是令人惊讶。

顺便说一句-我有一个涉及模板功能的解决方案。 我们只需要在模板中输入typedef就可以了。

trans by 2019-10-24T04:55:23Z

异常-C ++中的对象销毁

在C ++中确切地销毁对象是什么意思? 因为没有垃圾收集器,我是否必须手动销毁它们? 异常如何发挥作用?

(注意:这是Stack Overflow的C ++ FAQ的一个条目。如果您想批评以这种形式提供FAQ的想法,则可以在开始所有这些操作的meta上进行发布。) 该问题在C ++聊天室中进行监控,C ++聊天室首先出现了FAQ想法,因此,提出这个想法的人很可能会读懂您的答案。)

trans by 2019-10-04T07:49:32Z

在C ++中,构造函数和析构函数可以是内联函数吗?

VC ++使在类声明内联函数中实现的函数成为可能。

如果我按如下声明一个类Foo,那么CONSTRUCTOR和DESTRUCTOR内联函数是吗?

class Foo 
{
    int* p;
public:
    Foo() { p = new char[0x00100000]; }
    ~Foo() { delete [] p; }
};

{
    Foo f;
    (f);
}
trans by 2019-10-02T04:52:15Z

构造函数引发异常时,将运行哪些析构函数?

在C ++中,如果构造函数引发异常,那么将运行哪些析构函数?

特别是,如果异常在初始化列表或正文中,它会有所不同吗?

另外,继承和成员呢? 大概所有已完工的建筑都会被破坏。 如果仅构造一些成员,那么只有那些成员会被破坏吗? 如果存在多个继承,那么所有完成的构造函数都会被破坏吗? 虚拟继承会改变什么吗?

trans by 2019-09-28T02:54:38Z

.net - 在C#中使用IDisposable与析构函数有什么区别?

我何时在类上实现IDispose而不是析构函数? 我读过这篇文章,但我仍然忽略了这一点。

我的假设是,如果我在一个对象上实现IDispose,我可以明确地“破坏”#39; 它等待垃圾收集器这样做。 它是否正确?

这是否意味着我应该总是在对象上显式调用Dispose? 这有什么常见的例子?

trans by 2019-08-14T17:56:44Z

何时调用C ++析构函数?

基本问题:一个程序什么时候打电话给一个班级&#39; C ++中的析构函数方法? 有人告诉我,只要一个物体超出范围或受到delete的影响就会被调用

更具体的问题:

1)如果通过指针创建对象并且稍后删除该指针或给出指向的新地址,那么它所指向的对象是否会调用其析构函数(假设没有其他指向它)?

2)关注问题1,什么定义了一个对象何时超出范围(不是关于对象何时离开给定的{block})。 那么,换句话说,什么时候是一个析构函数调用链表中的对象?

3)你想要手动调用析构函数吗?

trans by 2019-08-13T14:39:47Z

1 2 下一页 共2页