2016-06-20 47 views
16
#include <vector> 

class Object 
{ 
}; 

int main() 
{ 
    Object myObject; 
    std::vector<int> myVector; 
} 

編譯器發出:爲什麼編譯器在聲明對象std :: vector時未發出警告但從未使用?

myVector無警告。爲什麼?有什麼辦法可以啓用它嗎?

+2

在C++中,構造函數和析構函數可以包含非平凡邏輯。因此,一般來說,看似未使用的變量聲明是否可以被消除是不確定的。 – pyon

+1

當你向對象添加一個不平凡的零參數構造函數時它會發出警告嗎? – lorro

回答

20

無論是否聲明(並因此初始化並在某個點上破壞)任意對象都具有可見的副作用,通常無法確定。構造函數可能調用的定義對編譯器來說是未知的,或者它可能依賴於外部狀態或任何使問題不可判定的其他方面。

在你的第一種情況下,構造函數是微不足道的(甚至沒有聲明),析構函數也是如此。由於Object沒有成員,因此很容易檢測到Object foo確實沒有任何成員。

std::vector具有可與一個非平凡的析構函數來分配存儲器(外部狀態+函數,其定義可能不是已知的(new ...))在一起的非平凡的構造(也外部狀態+函數,其定義可能是未知(delete ...))。在這種情況下,推理是否可以安全地移除聲明(因此發出警告暗示您可能應該),因此編譯器必須在代碼中留下聲明(並且必須假定聲明存在原因)。

一個主要的例子是std::lock_guard它被用來鎖定一個互斥體,當它被構造時它會在破壞時自動解鎖。只要對象在範圍內,互斥就被保持;一般而言,您根本不會訪問std::lock_guard對象 - 但是聲明它是有用的。這是工作中的RAII原則。

在這種情況下發出警告會造成滋擾,導致人們關閉警告,反過來會使警告無效。 (甚至可以將編譯器設計爲只在優化期間刪除聲明時才發出警告,這也是爲什麼某些警告僅在啓用某些優化時才顯示的原因。)

6

此警告僅爲平凡類型生成。編譯器無法找到構造是否會調用任何外部函數。如果你爲你的Object類添加一個構造函數,那麼編譯器也會發出警告。 GCC允許標籤,它應該產生這樣的警告類型,可以使用__attribute__((warn_unused))做到這一點:

http://coliru.stacked-crooked.com/a/0130c8ef29c121a1

例如:

class __attribute__((warn_unused)) Object 
{ 
    public: 
    Object(){} 
    void use() {} 
}; 

int main() 
{ 
    Object myObject; // will give : warning: unused variable 'myObject' [-Wunused-variable] 
    //myObject.use(); // uncomment to hide this warning 
} 

[編輯]

從GCC屬性頁:https://gcc.gnu.org/onlinedocs/gcc/C_002b_002b-Attributes.html

warn_unused對於具有非平凡構造函數和/或 析構函數的C++類型,編譯器無法確定此類型的變量是否真的未被使用(如果未被引用)。這個 類型屬性通知編譯器,如果這些類型的變量看起來像未被使用那樣應該被 警告,就像 基本類型的變量一樣。該屬性適用於只有 表示值的類型,例如std :: string;它不適用於控制資源的 類型,例如std :: lock_guard。

C中也接受此屬性,但它不是必需的,因爲C 沒有構造函數或析構函數。

+1

那麼,libstdC++應該用這個屬性標記它的大部分類型?他們應該有一個屬性no_warn_unused鎖定和類似的類型,並默認警告? –

+2

@MarcGlisse你是對的(我的意思是標記99%的libstdC++),並且在這裏有關於這個問題的公開討論:https://gcc.gnu.org/bugzilla/show_bug.cgi?id = 55203。 – marcinj

+1

我同意馬克,它應該是默認行爲。 – Jovini

2

除了上面的答案,還請檢查您的編譯器文檔。可以設置一些編譯器,以便它們不會多次顯示相同的警告。如果您註釋掉「myObject」的聲明,則可能會收到與「myVector」相同的警告。用「mObject」首先產生這個警告,你不會得到「myVector」的警告。

編譯器在警告情況下的行爲非常特定於編譯器,所以不要認爲所有編譯器的工作原理都是一樣的。 :)

相關問題