2012-03-17 21 views
0

是否有任何編譯器的標準佈局類型的佈局要求也不適用於普通可複製類型?特別是,關鍵規則是指向該類型的指針是指向其第一個成員的指針(其中基類將被視爲在派生類之前出現)。也就是說,該類型的地址與其基本類型是相同的地址。Trivially始終可僞造的僞標準佈局?

在代碼中,是否有任何常見的編譯器,其中以下實際上不會工作。對我來說這似乎很常見,所以我很驚訝它在C++ 11中沒有標準化。我知道肯定這在GCC中有效,我相信它在MSVC中工作(儘管我可能是錯的)。在哪個非歷史編譯器中,上述內容不能按預期工作?


擴展示例

上面的例子顯示了基本的問題,但可能不會顯示,會得到一個有意圖。這是一個稍微冗長的例子。基本上任何人都可以調用「發送」來排隊消息,然後稍後會通過回退到其實際類型來發送每條消息。

struct header { int len, id; } 
struct derived : public header { int other, fields; } 

void send(header * msg) 
{ 
    char * buffer = get_suitably_aligned_buffer(msg->len); 
    memcpy(buffer, msg, msg->len); 
} 

void dispatch(char * buffer) 
{ 
    header * msg = static_cast<header*>(buffer); 
    if(msg->id == derived_id) 
    handle_derived(static_cast<derived*>(msg)); 
} 


derived d; 
d.len = sizeof(d); 
d.id = deirved_id; 
send(&d); 

... 
char * buffer = get_the_buffer_again(); 
dispatch(buffer); 

它仍然省略了許多方面,但關鍵部分顯示。

+6

是什麼讓你認爲'memcpy'ing對象是C++中的「常見做法」? – 2012-03-17 17:20:05

+3

我不明白你爲什麼要使用賦值操作符來做其他操作?我很少看到C++ – 111111 2012-03-17 17:21:31

+0

@LightnessRacesinOrbit中的memcpy,因爲我已經在很多代碼中看到了它。此外,該標準提供了'memcpy'ing對象的規則,但並不能保證這種確切的情況。 – 2012-03-17 17:22:06

回答

1

是的,只要單一繼承存在,人們就一直用C++來做這件事。是的,這基本上是合理的。不,這個標準不支持。它是普遍支持的嗎?可能吧,但你已經知道那不是重點。這種問題是標準化應該消除的問題。

無論好壞,C++都提供瞭解決這個問題的辦法,儘管它明顯不那麼優雅。

問題是,派生類中的非靜態數據成員不一定在基本成員之後跟隨相同的填充,就好像它們直接拼接到基本中一樣。

但標準佈局結構的union具有共同的初始序列(故意避免繼承)確實收到此保證。

struct header { int len, id; } 

union derived { 
    struct { 
     header h; 
     int payload; 
    } fmt1; 

    struct { 
     header h; // repetitive 
     double payload; 
    } fmt2; 

    // etc for all message types 
}; 

佈局可能實際上不同空時基類乘法包括,尤其是,如果第一非靜態數據成員是相同類型的空基類。繼承(仍然)不能做到這一點的原因可能是他們厭倦了編寫空基的特例。

+0

我知道佈局可能不同於僞基礎作爲fisrt成員,而不是(通過填充),但我很好。我希望避免這個解決方案,因爲你指出的確切原因,它並不優雅。特別是因爲我沒有試圖與另一種語言溝通,這完全是C++到C++。謝謝。 – 2012-03-18 05:41:24

1

我知道肯定這在GCC中有效,我相信它在MSVC中工作(儘管我可能是錯的)。

不,你不知道。你已經在這些編譯器上運行了一些不會中斷的例子。這不同於知道「肯定」任何東西。

未定義的行爲未定義。 GCC的下一個版本可能會破壞你的代碼。 Visual Studio的下一個版本可能會破壞你的代碼。的確,編譯版本或者某些優化可能會破壞你的代碼。

遵循該標準是唯一可以「確切知道」任何關於您所得到的方法。做你正在做的事情不是實現定義的行爲;這是undefined的行爲。所以你不能相信你會得到一個合理的答案,即使它出現工作。

+0

是的,它保證了標準佈局,但我的類型只是可複製的,因此保證不成立。這就是爲什麼我感到驚訝,差別非常小我不明白爲什麼保證不是爲那些可以複製的類型。 – 2012-03-17 18:20:34

+0

@ edA-qamort-ora-y:你的類型*不是*標準佈局的方式是什麼? – 2012-03-17 18:21:26

+0

這個例子顯然是非常基本的,它沒有表現出意圖,只是潛在的問題。我不使用char *的原因是因爲實際的'copy'函數使用'base'類指針中的一些數據(在我的情況下,這個長度實際上是一個成員變量)。 – 2012-03-17 18:22:46