2009-09-24 136 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