2016-07-14 67 views
2

我正在寫一個文件處理類,我希望它具有的功能之一是「短途旅行」,您暫時尋求文件的一部分,然後回頭。我想這是自動完成的。這個想法是我有一個像我的文件類下面的代碼:C++值elision和析構函數?

file.excursion(512); 

這將返回,只是持有的遊覽對象:

struct File { 
    ... 
    struct Excursion { 
     Excursion(File& file, off64_t new_off) 
      : pi_(make_shared<impl>(file, new_off)) {} 

    private: 
     struct impl { 
      impl(File& file, off64_t new_off) 
       : file(file), off(file.tell()) { 
       file.seek(new_off); 
      } 

      ~impl() { 
        file.seek(off); 
      } 

      File &file; 
      off64_t off; 
     }; 

     shared_ptr<impl> pi_; 
    }; 

    Excursion excursion(off64_t off) { 
     return Excursion(*this, off); 
    } 
}; 

然後,我可以喜歡的東西開始遊覽引用文件和當前偏移量。當該對象超出範圍時,它會自動恢復文件偏移量。這使得代碼必須跳過文件才能解析它。我的問題是,如果我從file.excursion()返回Excursion對象並且不將它分配給任何東西,C++是否允許完全忽略該值而不調用析構函數?

編輯:

每下面,茲比涅克Vyskovsky - kvr000是正確的,析構函數不是省略。 但是,執行如上所示的偏移返回一個對象,由於它沒有分配給任何東西,所以它立即被破壞。

here,因爲它是從該函數評估中返回的臨時值,所以該對象在評估創建表達式的最後一步時被銷燬。因此,而不是一直持續到封閉範圍的結束。因此,如果不將偏移對象分配給更高範圍的變量,該技術就無法工作。

這會工作:

Excursion ex = file.excursion(512); 

但它是一個見仁見智必須有一個虛擬變量躺在附近是否是正確的事情。

+0

檢查「彷彿」規則。 –

+0

你能澄清一下你的用法嗎?你的意思就像'Excursion foo(){return file.excursion(512); }'? – Barry

+1

不,如果你請求了析構函數,通常不能省略析構函數。唯一可以省略的副作用是副本(當然還有中間體的破壞)。 –

回答

3

不,它不能忽略析構函數。

編譯器可以進行優化,只有在部分代碼發現沒有任何影響的情況下才能刪除代碼。當你從析構函數調用影響其他對象的全局狀態的另一個方法時,這顯然不是這種情況。

+0

確實如此。只有優化器足夠聰明才能發現整個構造+破壞對是無效的,它可以將其全部移除。 – Angew

+0

事實上,它可以優化出一些有副作用的代碼 - 複製elision – stryku

+0

@stryku:複製elision是一個特殊情況,在標準中特別指出。在一般情況下,它不能刪除有副作用的代碼。 –