2009-09-24 165 views
4

如果我有這樣一個全局變量列表...存儲在內存中的變量

int a; 
char b; 
float c[10]; 
double d[3]; 

,我有一個類中列出的變量相同的序列......

class test_type 
{ 
    int a; 
    char b; 
    float c[10]; 
    double d[3]; 
} 

是否保證所有變量在內存中的排列是相同的。即'b'保證在全局列表和類列表中的'a'之後立即存儲?

編輯:我問,因爲我想A)從一個將數據複製到另一個作爲「很多工作」和B)我想檢查的工作很多他們之間的差異。如果主要問題的答案是「否」,那麼是否有人對我如何解決問題有任何建議,最好是儘可能保持現有代碼不變。

回答

8

不,我不認爲C++標準可以保證任何關於全局變量的內存佈局。

+2

它確實保證了一些東西。保留了具有相同訪問說明符的連續聲明的類/結構元素的順序。不過,可能會涉及一些填充。 – sellibitze 2009-09-24 14:04:23

+2

是的,但Jesper說「全局變量」。 – Skilldrick 2009-09-24 14:10:06

+0

正確。我錯過了,對不起。 – sellibitze 2009-09-25 14:50:41

0

內存分配依賴於編譯器。因此,連續分配或全局和類成員變量的相同分配無法得到保證。

0

不,你不能依賴那個。這取決於編譯器如何爲變量分配內存。

0

不,不能保證。根據你想要做什麼,你可以使用指針成員操作符來確保你知道成員變量的相對地址。

所以在你的類:

class test_type 
{ 
    int a; 
    char b; 
    float c[10]; 
    double d[3]; 
} 

void* pa = &test_type::a; 
void* pb = &test_type::b; 
void* pc = &test_type::c; 
void* pd = &test_type::d; 

void main() 
{ 
    std::cout << "Relative address of member 'a' " << (int)pa << std::endl; 
    std::cout << "Relative address of member 'b' " << (int)pb << std::endl; 
    std::cout << "Relative address of member 'c' " << (int)pc << std::endl; 
    std::cout << "Relative address of member 'd' " << (int)pd << std::endl; 
} 

據我知道它正在與MSVC和gcc爲好。

+2

這是因爲在類/結構體中定義的變量的順序絕對是有保證的。這只是全局變量而已。 – kdgregory 2009-09-24 12:26:47

+0

也許你是對的,但我的解決方案並不意味着任何額外的操作,並通常說它不依賴於一個原則,可以通過實施輕易改變。 (我不完全確定這是如何影響對齊問題的......) – progician 2009-09-24 13:25:56

+0

您的「解決方案」演示了已知的事實。它不能解決OP希望通過單一操作將全局變量複製到結構中的期望目標。 – kdgregory 2009-09-24 15:00:34

1

C/C++標準不要求變量按其聲明的順序存儲。所以編譯器可以按照他們想要的順序自由存儲變量。但保證它們將按其聲明的順序進行初始化。對於全局和類成員變量都是如此。

有關全局變量的一些說明:在編譯單元中,它們將按指定的順序進行初始化,但本保證不跨編譯單元應用

0

米克 - 以你想要做什麼(複製/測試),你只需要簡單地

  • 添加一個構造函數來test_type類和非構造init_from_globals()(其代碼逐個複製4個值,將數組複製到循環或通過memcopy複製)。

  • 添加「diff_from_globals()」方法,這再次DIFFS的4名成員分別

這是一個有點比你想要的東西儘可能的實現,但包裹在一個方法效率較低/優雅,在典雅是從代碼的其餘部分完全隱藏:)

6

爲什麼不簡單地使用類型test_type的全局對象,而不是定義多個全局變量?

class test_type 
{ 
    int a; 
    char b; 
    float c[10]; 
    double d[3]; 
}; 

test_type global; 

現在,用一個「global」副本初始化一個新的test_type對象是小菜一碟。

0

我認爲人們缺少重點。假設任何佈局總是很危險的,因爲這可能會從CPU變爲CPU,編譯器到編譯器甚至是優化程度。

C作爲,如果你這樣寫++會生成一個默認的拷貝賦值函數:

class test_type 
{ 
    int a; 
    char b; 
    float c[10]; 
    double d[3]; 
public: 
    test_type &operator=(const test_type &other) 
    { 
    // copy all of the members one by one. 
    } 
} 

唯一需要注意的是,默認的操作只是複製成員,包括指針。如果你已經動態地分配了一個附加在指針上的東西,你將不得不處理新的內存分配和數據在操作符中顯式複製。

+0

那麼?在這種情況下,隱式生成的賦值運算符不會造成任何影響。 – sellibitze 2009-09-24 14:48:35

+0

當然不是。我認爲創建默認操作員正確工作的類是一種很好的做法。例如,我使用std :: string而不是char *。 – 2009-09-24 16:54:37