pbootcms网站模板|日韩1区2区|织梦模板||网站源码|日韩1区2区|jquery建站特效-html5模板网

“空"構造函數或析構函數會與生成的構造函

Will an #39;empty#39; constructor or destructor do the same thing as the generated one?(“空構造函數或析構函數會與生成的構造函數做同樣的事情嗎?)
本文介紹了“空"構造函數或析構函數會與生成的構造函數做同樣的事情嗎?的處理方法,對大家解決問題具有一定的參考價值,需要的朋友們下面隨著小編來一起學習吧!

問題描述

假設我們有一個(玩具)C++ 類,如下所示:

Suppose we have a (toy) C++ class such as the following:

class Foo {
    public:
        Foo();
    private:
        int t;
};

由于沒有定義析構函數,C++編譯器應該自動為類Foo創建一個.如果析構函數不需要清理任何動態分配的內存(也就是說,我們可以合理地依賴編譯器給我們的析構函數),則會定義一個空的析構函數,即.

Since no destructor is defined, a C++ compiler should create one automatically for class Foo. If the destructor does not need to clean up any dynamically allocated memory (that is, we could reasonably rely on the destructor the compiler gives us), will defining an empty destructor, ie.

Foo::~Foo() { }

和編譯器生成的一樣嗎?一個空的構造函數呢——也就是說,Foo::Foo() { }?

do the same thing as the compiler-generated one? What about an empty constructor -- that is, Foo::Foo() { }?

如果存在差異,它們存在于何處?如果不是,一種方法是否優于另一種方法?

If there are differences, where do they exist? If not, is one method preferred over the other?

推薦答案

它會做同樣的事情(本質上什么都沒有).但這和沒寫不一樣.因為編寫析構函數將需要一個工作的基類析構函數.如果基類析構函數是私有的或者有任何其他原因無法調用它,那么你的程序就有問題.考慮這個

It will do the same thing (nothing, in essence). But it's not the same as if you didn't write it. Because writing the destructor will require a working base-class destructor. If the base class destructor is private or if there is any other reason it can't be invoked, then your program is faulty. Consider this

struct A { private: ~A(); };
struct B : A { }; 

沒關系,只要您不需要銷毀 B 類型的對象(因此,隱式為 A 類型) - 就像您從不對動態創建的對象調用 delete 一樣,或者您從不創建對象它首先.如果這樣做,則編譯器將顯示適當的診斷信息.現在,如果您明確提供一個

That is OK, as long as your don't require to destruct an object of type B (and thus, implicitly of type A) - like if you never call delete on a dynamically created object, or you never create an object of it in the first place. If you do, then the compiler will display an appropriate diagnostic. Now if you provide one explicitly

struct A { private: ~A(); };
struct B : A { ~B() { /* ... */ } }; 

那個會嘗試隱式調用基類的析構函數,并且會在 ~B 的定義時間導致診斷.

That one will try to implicitly call the destructor of the base-class, and will cause a diagnostic already at definition time of ~B.

還有一個區別在于析構函數的定義和對成員析構函數的隱式調用.考慮這個智能指針成員

There is another difference that centers around the definition of the destructor and implicit calls to member destructors. Consider this smart pointer member

struct C;
struct A {
    auto_ptr<C> a;
    A();
};

假設C類型的對象是在.cpp文件中A的構造函數定義中創建的,該文件也包含structC<的定義/代碼>.現在,如果您使用 struct A,并且需要銷毀 A 對象,則編譯器將提供析構函數的隱式定義,就像上面的情況一樣.該析構函數還將隱式調用 auto_ptr 對象的析構函數.這將刪除它持有的指針,該指針指向 C 對象 - 不知道 C 的定義!出現在 .cpp 文件中,其中定義了 struct A 的構造函數.

Let's assume the object of type C is created in the definition of A's constructor in the .cpp file, which also contains the definition of struct C. Now, if you use struct A, and require destruction of an A object, the compiler will provide an implicit definition of the destructor, just like in the case above. That destructor will also implicitly call the destructor of the auto_ptr object. And that will delete the pointer it holds, that points to the C object - without knowing the definition of C! That appeared in the .cpp file where struct A's constructor is defined.

這實際上是實現 pimpl 成語的一個常見問題.這里的解決方案是添加一個析構函數并在 .cpp 文件中提供它的空定義,其中定義了結構體 C.當它調用其成員的析構函數時,它就會知道struct C的定義,并且可以正確調用它的析構函數.

This actually is a common problem in implementing the pimpl idiom. The solution here is to add a destructor and provide an empty definition of it in the .cpp file, where the struct C is defined. At the time it invokes the destructor of its member, it will then know the definition of struct C, and can correctly call its destructor.

struct C;
struct A {
    auto_ptr<C> a;
    A();
    ~A(); // defined as ~A() { } in .cpp file, too
};

請注意,boost::shared_ptr 沒有這個問題:當它的構造函數以某些方式被調用時,它需要一個完整的類型.

Note that boost::shared_ptr does not have that problem: It instead requires a complete type when its constructor is invoked in certain ways.

它在當前 C++ 中的另一個不同點是當您想在具有用戶聲明的析構函數的對象上使用 memset 和朋友時.這些類型不再是 POD(純舊數據),并且不允許進行位復制.請注意,這種限制并不是真正需要的 - 下一個 C++ 版本已經改善了這種情況,因此只要不進行其他更重要的更改,它仍然允許您對此類類型進行位復制.

Another point where it makes a difference in current C++ is when you want to use memset and friends on such an object that has a user declared destructor. Such types are not PODs anymore (plain old data), and these are not allowed to be bit-copied. Note that this restriction isn't really needed - and the next C++ version has improved the situation on this, so that it allows you to still bit-copy such types, as long as other more important changes are not made.

既然你要求構造函數:嗯,對于這些事情來說都是一樣的.請注意,構造函數還包含對析構函數的隱式調用.在像 auto_ptr 這樣的東西上,這些調用(即使實際上沒有在運行時完成——這里純粹的可能性已經很重要了)將造成與析構函數相同的危害,并且在構造函數中的某些東西拋出時發生——然后編譯器需要調用析構函數的成員.這個答案使用默認構造函數的隱式定義.

Since you asked for constructors: Well, for these much the same things are true. Note that constructors also contain implicit calls to destructors. On things like auto_ptr, these calls (even if not actually done at runtime - the pure possibility already matters here) will do the same harm as for destructors, and happen when something in the constructor throws - the compiler is then required to call the destructor of the members. This answer makes some use of implicit definition of default constructors.

此外,我在上面提到的析構函數的可見性和 POD 性也是如此.

Also, the same is true for visibility and PODness that i said about the destructor above.

關于初始化有一個重要區別.如果您放置了一個用戶聲明的構造函數,您的類型將不再接收成員的值初始化,并且由您的構造函數進行任何需要的初始化.示例:

There is one important difference regarding initialization. If you put a user declared constructor, your type does not receive value initialization of members anymore, and it is up to your constructor to do any initialization that's needed. Example:

struct A {
    int a;
};

struct B {
    int b;
    B() { }
};

在這種情況下,以下總是正確的

In this case, the following is always true

assert(A().a == 0);

雖然以下是未定義的行為,因為 b 從未被初始化(您的構造函數省略了它).該值可能為零,但也可能是任何其他奇怪的值.試圖從這樣一個未初始化的對象中讀取會導致未定義的行為.

While the following is undefined behavior, because b was never initialized (your constructor omitted that). The value may be zero, but may aswell be any other weird value. Trying to read from such an uninitialized object causes undefined behavior.

assert(B().b == 0);

new 中使用這種語法也是如此,例如 new A()(注意末尾的括號 - 如果省略它們,則不會進行值初始化,并且由于沒有用戶聲明的構造函數可以初始化它,a 將保持未初始化).

This is also true for using this syntax in new, like new A() (note the parentheses at the end - if they are omitted value initialization is not done, and since there is no user declared constructor that could initialize it, a will be left uninitialized).

這篇關于“空"構造函數或析構函數會與生成的構造函數做同樣的事情嗎?的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!

【網站聲明】本站部分內容來源于互聯網,旨在幫助大家更快的解決問題,如果有圖片或者內容侵犯了您的權益,請聯系我們刪除處理,感謝您的支持!

相關文檔推薦

How can I read and manipulate CSV file data in C++?(如何在 C++ 中讀取和操作 CSV 文件數據?)
In C++ why can#39;t I write a for() loop like this: for( int i = 1, double i2 = 0; (在 C++ 中,為什么我不能像這樣編寫 for() 循環: for( int i = 1, double i2 = 0;)
How does OpenMP handle nested loops?(OpenMP 如何處理嵌套循環?)
Reusing thread in loop c++(在循環 C++ 中重用線程)
Precise thread sleep needed. Max 1ms error(需要精確的線程睡眠.最大 1ms 誤差)
Is there ever a need for a quot;do {...} while ( )quot; loop?(是否需要“do {...} while ()?環形?)
主站蜘蛛池模板: CXB船用变压器-JCZ系列制动器-HH101船用铜质开关-上海永上船舶电器厂 | 澳门精准正版免费大全,2025新澳门全年免费,新澳天天开奖免费资料大全最新,新澳2025今晚开奖资料,新澳马今天最快最新图库 | 健身器材-健身器材厂家专卖-上海七诚健身器材有限公司 | 阻垢剂-反渗透缓蚀阻垢剂厂家-山东鲁东环保科技有限公司 | 万濠投影仪_瑞士TRIMOS高度仪_尼康投影仪V12BDC|量子仪器 | 无锡不干胶标签,卷筒标签,无锡瑞彩包装材料有限公司 | 高低温万能试验机-复合材料万能试验机-馥勒仪器 | 组织研磨机-高通量组织研磨仪-实验室多样品组织研磨机-东方天净 传递窗_超净|洁净工作台_高效过滤器-传递窗厂家广州梓净公司 | 卫浴散热器,卫浴暖气片,卫生间背篓暖气片,华圣格浴室暖气片 | 大_小鼠elisa试剂盒-植物_人Elisa试剂盒-PCR荧光定量试剂盒-上海一研生物科技有限公司 | 流程管理|流程管理软件|企业流程管理|微宏科技-AlphaFlow_流程管理系统软件服务商 | 彩信群发_群发彩信软件_视频短信营销平台-达信通 | 神超官网_焊接圆锯片_高速钢锯片_硬质合金锯片_浙江神超锯业制造有限公司 | ★店家乐|服装销售管理软件|服装店收银系统|内衣店鞋店进销存软件|连锁店管理软件|收银软件手机版|会员管理系统-手机版,云版,App | 双能x射线骨密度检测仪_dxa骨密度仪_双能x线骨密度仪_品牌厂家【品源医疗】 | 滤芯,过滤器,滤油机,贺德克滤芯,精密滤芯_新乡市宇清流体净化技术有限公司 | 氧化锆陶瓷_氧化锆陶瓷加工_氧化锆陶瓷生产厂家-康柏工业陶瓷有限公司 | 网站建设,北京网站建设,北京网站建设公司,网站系统开发,北京网站制作公司,响应式网站,做网站公司,海淀做网站,朝阳做网站,昌平做网站,建站公司 | 会议会展活动拍摄_年会庆典演出跟拍_摄影摄像直播-艾木传媒 | 国际金融网_每日财经新资讯网| 根系分析仪,大米外观品质检测仪,考种仪,藻类鉴定计数仪,叶面积仪,菌落计数仪,抑菌圈测量仪,抗生素效价测定仪,植物表型仪,冠层分析仪-杭州万深检测仪器网 | 电表箱-浙江迈峰电力设备有限公司-电表箱专业制造商 | 智慧食堂_食堂管理系统_食堂订餐_食堂消费系统—客易捷 | 窖井盖锯圆机_锯圆机金刚石锯片-无锡茂达金刚石有限公司 | 时代北利离心机,实验室离心机,医用离心机,低速离心机DT5-2,美国SKC采样泵-上海京工实业有限公司 工业电炉,台车式电炉_厂家-淄博申华工业电炉有限公司 | 云南成人高考网| 磁力抛光机_磁力研磨机_磁力去毛刺机_精密五金零件抛光设备厂家-冠古科技 | 锥形螺带干燥机(新型耙式干燥机)百科-常州丰能干燥工程 | 合肥升降机-合肥升降货梯-安徽升降平台「厂家直销」-安徽鼎升自动化科技有限公司 | 温州中研白癜风专科_温州治疗白癜风_温州治疗白癜风医院哪家好_温州哪里治疗白癜风 | 英国雷迪地下管线探测仪-雷迪RD8100管线仪-多功能数字听漏仪-北京迪瑞进创科技有限公司 | 玉米加工设备,玉米深加工机械,玉米糁加工设备.玉米脱皮制糁机 华豫万通粮机 | 安全阀_弹簧式安全阀_美标安全阀_工业冷冻安全阀厂家-中国·阿司米阀门有限公司 | 沥青车辙成型机-车托式混凝土取芯机-混凝土塑料试模|鑫高仪器 | 吸污车_吸粪车_抽粪车_电动三轮吸粪车_真空吸污车_高压清洗吸污车-远大汽车制造有限公司 | 旋振筛_不锈钢旋振筛_气旋筛_旋振筛厂家—新乡市大汉振动机械有限公司 | 异噻唑啉酮-均三嗪-三丹油-1227-中北杀菌剂厂家 | 仓储笼_仓储货架_南京货架_仓储货架厂家_南京货架价格低-南京一品仓储设备制造公司 | 办公室家具_板式办公家具定制厂家-FMARTS福玛仕办公家具 | 粤丰硕水性环氧地坪漆-防静电自流平厂家-环保地坪涂料代理 | 风电变桨伺服驱动器-风电偏航变桨系统-深圳众城卓越科技有限公司 |