1. 程式人生 > >Guru of the Week 條款22:物件的生存期(第一部分)

Guru of the Week 條款22:物件的生存期(第一部分)

GotW #22 Object Lifetimes – Part I<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

著者:Herb Sutter

翻譯:K ][ N G of @rk™

[宣告]:本文內容取自www.gotw.ca網站上的Guru of the Week欄目,其著作權歸原著者本人所有。譯者kingofark在未經原著者本人同意的情況下翻譯本文。本翻譯內容僅供自學和參考用,請所有閱讀過本文的人不要擅自轉載、傳播本翻譯內容;下載本翻譯內容的人請在閱讀瀏覽後,立即刪除其備份。譯者

kingofark對違反上述兩條原則的人不負任何責任。特此宣告。

Revision 1.0

Guru of the Week條款22:物件的生存期(第一部分)

難度:5 / 10

(“生存,還是滅亡……[譯註:這是莎士比亞所著《哈姆雷特》中的名句] 一個物件何時才算是真實存在的?這個問題用來考察一個物件何時才能被安全的使用。)

[Problem]

[問題]

評述下面的程式段。#2處的程式碼使安全和/或合法的嗎?請對你的回答做出解釋。

[解答]

是的,#2處的程式碼是安全且合法的(如果只考慮這部分程式碼的話),但:

a)函式作為一個整體,它是不安全的,而且

b)這樣做是一個壞習慣。

[

為什麼#2是安全的(如果只考慮這部分程式碼的話)?]

C++標準草案明確規定,允許這種程式碼出現。現場的析構和重構造(in-place destruction and reconstruction)不會使rt這個引用失效。(當然,你不能在t.~T()placement new之間使用trt,因為在那段時期裡不存在任何物件。我們還假設T::operator&()沒有被過載,即沒有被用來做「返回物件之地址」以外的其它事情。

我們之所以說“如果只考慮這部分程式碼的話,#2就是安全的”,是因為f()作為一個整體而言,可能不是異常安全的(exception-safe):

[為什麼函式是不安全的?

]

如果在呼叫T(2)的時候,T的建構函式有丟擲異常的可能,那麼f()就不是異常安全的。考慮其原因:如果T(2)丟擲異常,那麼在原來’t’所在的記憶體區域中將不會有新的物件被構造,而在函式末尾T::~T()仍然被正常呼叫(因為t是一個自動變數[automatic variable]),而且正如程式碼中的註釋所述,“t被再次銷燬”。這即是說,’t’會被構造一次,卻被銷燬兩次(嗚呼呀)。這將導致容易產生無法預見的副作用,比如core dumps

[為什麼這是個壞習慣?]

如果忽略異常安全性的問題,那麼程式碼在這樣的設定下恰好就能夠正常工作,這是因為程式設計師此時知道被構造和銷燬之物件的具體型別。這即是說,該物件是一個T,並被作為一個T來被銷燬和重新構造。

在實際的程式碼中,這種技術(即便真是編碼所需)幾乎不會被使用,並且這樣做也是非常壞的習慣;原因是:如果其出現在成員函式中,那麼其將會充滿(有時難以捉摸的)危險:

現在這種技術還算安全嗎?基本上來說,不安全。考慮下面的程式碼:

如果”/*AAA*/””T”,那麼#2處的程式碼仍然可行,即使”/*BBB*/”不是”T” ”/*BBB*/”可能是T的基類)。

如果”/*AAA*/””U”(譯註:而不是”T”),那麼無論”/*BBB*/”是什麼,都已經毫無懸念了。大概你所能期待的最好結果就是一個及時的core dump,因為對t.f()的呼叫將物件“切割(slices)”了。這裡說的“切割”是指:t.f()用屬於另一個不同型別的物件替換了原來的物件——這即是說函式使用了T而不是U。即便是你意欲編寫不可移植的程式碼,你也無法知曉「當原來U所在的記憶體區域被T物件之資料抹蓋以後,其被作為U是否還可用?」。固然還是有情況尚佳的機率,但是請不要走到那個地步……這絕不是一次良好的實踐。

本期GotW包含了一些基本的、有關現場析構和重構(in-place destruction and reconstruction)的安全性問題和切割問題。這為下期的“GotW條款23:物件生存期(第二部分)”作下鋪墊。

(完)

相關推薦

Guru of the Week 條款20程式碼的複雜性第一部分

GotW #20 Code Complexity – Part I<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /> 著者:Herb Sutter 翻譯:K ][

Guru of the Week 條款21程式碼的複雜性第二部分

GotW #21 Code Complexity – Part II<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /> 著者:Herb Sutter 翻譯:K ]

Guru of the Week 條款22物件生存第一部分

GotW #22 Object Lifetimes – Part I<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /> 著者:Herb Sutter 翻譯:K ]

Guru of the Week 條款09記憶體管理上篇

  GotW #09 Memory Management - Part I 著者:Herb Sutter 翻譯:kingofark [宣告]:本文內容取自www.gotw.ca網站上的Guru of the Week欄目,其著作權歸原著者本人所有。譯者kingofark在未經

Guru of the Week 條款06正確使用const

  GotW #06 Const-Correctness 著者:Herb Sutter 翻譯:kingofark [宣告]:本文內容取自www.gotw.ca網站上的Guru of the Week欄目,其著作權歸原著者本人所有。譯者kingofark在未經原著者本人同意的情

Guru of the Week 條款08GotW挑戰篇——異常處理的安全性

  GotW #08 CHALLENGE EDITION Exception Safety 著者:Herb Sutter 翻譯:kingofark [宣告]:本文內容取自www.gotw.ca網站上的Guru of the Week欄目,其著作權歸原著者本人所有。譯者king

Guru of the Week 條款16具有最大可複用性的通用Containers

GotW #16 Maximally Reusable Generic Containers<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />著者:Herb Sutter翻譯:kingofar

Guru of the Week 條款30附錄介面原則

它是這麼工作的:所謂“名稱搜尋”就是當你寫下一個“f(parm)”呼叫時,編譯器必須要決策出你想調哪個叫f的函式。(由於過載和作用域的原因,可能會有幾個叫f的函式。)Koenig lookup是這麼說的,如果你傳給函式一個class型別的實參(此處是parm,型別為NS::T),為了查詢這個函式名,編譯器被要

Guru of the Week 條款01: 變數的初始化

GotW #01 Variable Initialization 著者:Herb Sutter 翻譯:kingofark [宣告]:本文內容取自www.gotw.ca網站上的Guru of the Week欄目,其著作權歸原著者本人所有。譯者kingofark在未經原著者本人

c++11 條款22當使用Pimpl指向實現的指標時,在實現檔案裡定義特定的成員函式

條款22:當使用Pimpl(指向實現的指標)時,在實現檔案裡定義特定的成員函式         假如你曾經和過多的編譯構建時間抗爭過,你應該熟悉Pimpl(指向實現的指標)這個術語。這項技術是你可以把類的資料成員替換成一個指向實現類(結構)的指標,把原來在主類中的資料成員

Buggy Java CodeJava程式設計師最容易犯的10個錯第一部分

翻譯:叩丁狼教育吳嘉俊 Java語言最開始是為了互動電視機而開發的,隨著時間的推移,他已經廣泛應用各種軟體開發領域。基於面向物件的設計,遮蔽了諸如C,C++等語言的一些複雜性,提供了垃圾回收機制,平臺無關的虛擬機器技術,Java創造了一種前所未有的開發方式。另一方面,得益於Java提出的“一次編

Spring Boot 專欄HelloWord快速入門第一

寫在前面的話: 沒有好的文采,但是有一顆樂於分享心,希望用最精簡的語言,描繪每一個demo的構建過程,為開發者提供最容易上手的demo樣例。   SpringBoot簡介 Spring Boot來簡化Spring應用開發,約定大於配置, 去繁從簡(大體和SpringMv

ORBSLAM2學習DBoW2原始碼分析OrbVocabulary部分

{(w1,weight1),(w2,weight2),...,(wn,weightn)}的形式,就對應著這裡的BowVector。BowVector派生自public std::map<WordId, WordValue>,實際上就是public std::map<int, double&g

java核心(十二多線程第一

實用 implement cti size timer類 離開 syn ace final 一、多線程的實現方式 Java多線程實現方式主要有三種:繼承Thread類、實現Runnable接口、實現Callable接口通過FutureTask包裝器來創建Thread線程。

effective c++條款22將成員變數宣告為private

將成員變數宣告為private的三大理由: 1. 提供語法一致性:  如果將所有的變數都宣告為private,那麼當其他人使用這個類時,就不用糾結是以函式方式呼叫還是變數方式呼叫,更加節省時間。 #include <iostream> using namespa

PyDev of the Week: Jacqueline Kazil

This week we welcome Jacqueline Kazil (@JackieKazil) as our PyDev of the Week! She is the co-author of Data Wrangling with Python. Jacqueline is the creato

NRN video of the week: Burger King taps into artificial intelligence for new ads

Burger King has launched a new campaign with the "first ads entirely created by an A.I. to air on national television," according to a Sept. 27 release fro

PyDev of the Week: K Lars Lohn

This week we welcome K Lars Lohn (@2braids) as our PyDev of the Week! He has been a part of the Python community for quite a few years. You can learn a bit

PyDev of the Week: Marc Garcia

This week we welcome Marc Garcia (@datapythonista) as our PyDev of the Week! Marc is a core developer of pandas, a Python data analysis library. If you’d l

Marginally Interesting: Tool of the week (web edition): gotapi.com

Tweet This weeks tool of the week (well, not that every week actually g