2017-06-20 94 views
3

我只是偶然到從智能指針鑄造,想檢查是否static_cast可以在編譯時,下面是荒謬的斷言:爲何能的static_cast編譯鑄造的原料指針的智能指針

int main() 
{ 
    char foobar[4] = "Foo"; 
    std::unique_ptr<char[]> myptr = static_cast<decltype(myptr)>(foobar); 
    myptr.reset(); 
    return 0; 
} 

這裏會發生什麼是myptr嘗試免費foobar

我不是問什麼是智能指針或如何分配或修復上述問題。

我認爲這個問題應該在編譯時被捕獲,因爲這些類型應該完全不兼容。

爲什麼在編譯時檢測不到?

回答

7

static_cast導致的std::unique_ptr類似於您可以在下面的例子中看到的構造函數的調用

#include <iostream> 
#include <memory> 

using std::cout; 
using std::endl; 

class Something { 
public: 
    explicit Something(int) { 
     cout << __PRETTY_FUNCTION__ << endl; 
    } 
}; 

int main() { 
    auto something = static_cast<Something>(1); 
    (void) something; 
} 

如果你想知道爲什麼static_cast導致的std::unique_ptr構造可以解釋通話與標準以下引號(重點煤礦)

靜態澆鑄 [expr.static.cast/4]

的表達式e可以使用形式static_cast<T>(e)static_cast如果聲明T t(e);是公形成,對於一些發明臨時變量t(8.5)顯式轉換爲一個類型T。這種顯式轉換的效果與執行聲明和初始化相同,然後使用臨時變量作爲轉換的結果。表達式e被用作glvalue當且僅當初始化使用它作爲左值。

所以在您的示例基本上陣列被視爲一個參數的unique_ptr構造,然後將假想臨時隨後被用於初始化變量myptr(在大多數情況下,省音)

的構造即在你的例子是所謂的下面cppreference頁面(2)http://en.cppreference.com/w/cpp/memory/unique_ptr/unique_ptr

explicit unique_ptr(pointer p) noexcept; 

在這裏你會得到一個unique_ptr指向數組。

然後,當您撥打reset()時,unique_ptr會嘗試刪除具有自動生存期的變量並導致未定義的行爲。但是,編譯器不需要檢測到這一點。

+1

@StoryTeller修復!好點子 – Curious

4

代碼沒有意義,但語法是有效的,爲什麼它不是?

的這裏static_cast是基本相同:

std::unique_ptr<char[]> myptr = std::unique_ptr<char[]>(foobar); 

而且即使這是無意義的,因爲你不應該用手指向帶有自動生命週期的變量它不會使語法無效的指針。 static_cast本身就非常好。

這些類型不兼容,編譯器無法檢查指向static_cast的指針是否指向動態分配的內存,因此它編譯得很好。當然,正如你已經指出的那樣,這是非常不確定的行爲,所以這個程序的結果是不合理的,但這不是編譯器的工作來警告程序員。