久久久久久久av_日韩在线中文_看一级毛片视频_日本精品二区_成人深夜福利视频_武道仙尊动漫在线观看

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

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 ()?環形?)
主站蜘蛛池模板: 亚洲视频欧美视频 | 亚洲精品久久区二区三区蜜桃臀 | 99精品国产一区二区三区 | 久久精品成人 | av一区二区三区四区 | 天天综合久久 | 色综合一区二区 | 久草福利 | 99国产视频 | 91视频在线 | 国产精品久久久久久久免费观看 | 成人日韩av | 欧美精品一区二区蜜桃 | 一区二区三区视频在线观看 | 亚洲大片在线观看 | 日韩中文一区二区三区 | 欧美一区二区三区视频 | 国产一区二区精品在线观看 | 91佛爷在线观看 | 亚洲视频一区二区三区 | 成人av播放 | 国产真实乱对白精彩久久小说 | 欧美精品久久 | 我爱操| 精品久久久久久久久久久久久久 | 91热爆在线观看 | 久久一区二区av | 日韩一区二区三区在线观看 | 亚洲欧美日韩精品久久亚洲区 | 国产一区 | 国产在线精品一区二区三区 | 精品中文字幕一区二区三区 | 九九热在线精品视频 | www.亚洲.com | 亚av在线| 国产激情片在线观看 | 欧美日韩久久久 | 久久精品久久久久久 | 一区二区三区在线 | 欧美日韩不卡 | 精品视频在线观看 |