2016-02-11 3 views
1

Я возился с кодом, как следующее:C++ Союзов в памяти

union Data { 
    int i; 
    double x; 
    std::string str; 
    ~Data(){} 
}; 

union Data var = {.x = 31293.932}; 

std::cout << var.x << "\n"; 
std::cout << var.str << "\n"; 
std::cout << var.i << "\n"; 

Насколько я знаю, союза есть некоторые 64 бит, что написано после того, как я установил й элемент к некоторому числу с плавающей точкой. Затем я хочу увидеть соответствующую строку, считая, что я обрабатывал эти байты как char. Но я получаю ошибку сегментации, когда пытаюсь напечатать ее как строку. Почему это? Я инициализировал объединение, поэтому я предполагаю, что var.str также должен быть инициализирован.

+2

В принципе, бросая кучу байтов в слот памяти и надеясь, что вы можете обрабатывать эти байты как действительный объект 'std :: string', является рецептом для катастрофы. –

+3

Вы ожидаете, что включение членов в объединение магически позволяет им конвертировать из любого типа данных в любой другой тип данных, и это не так, как все работает. –

ответ

4

str не был сконструирован. если вы должны использовать str, вы должны либо предоставить ему конструктор, либо построить его через новое место размещения. Полный пример ниже

#include <iostream> 
#include <vector> 

using namespace std; 

union Data 
{ 
    int i; 
    double x; 
    std::string str; 
    Data() {} 
    Data(std::string st) : str(st) {} 
    ~Data() {} 
}; 

int main() 
{ 
    Data var; 
    var.x = 31293.932; 
    new (&var.str) std::string("Hello World!"); 


    std::cout << var.x << "\n"; 
    std::cout << var.str << "\n"; 
    std::cout << var.i << "\n"; 

//destroy it 
    var.str.std::string::~string(); 
} 

EDIT:

Просто расширить мой ответ немного ...

MSDN, кажется, есть n00bie дружественного объяснение о союзах, чем cppreference. Итак, отметьте: Unions - MSDN и Unions - cppreference

+0

Что такое «new (& var.str) std :: string (« Hello World! »); действительно делает? Разделяет ли он память с размером «Hello World!» или он просто вызывает конструктор для Data? – meguli

+0

Стоит добавить, что поскольку 'i',' x' и 'str' разделяют одно и то же пространство в памяти, присвоение' i' или 'x' после установки' str' приведет к повреждению 'str' и, возможно, сделает его незавершенным. – user4581301

+0

@meguli Это место Новое. Подробнее здесь: [Что используется для «размещения нового»?] (Http://stackoverflow.com/questions/222557/what-uses-are-there-for-placement-new) – user4581301

0

Вы должны использовать char для доступа к байтам в объединении. std::string не является типом POD и не может использоваться таким образом.

Попробуйте вместо этого:

union Data { 
    int i; 
    double x; 
    char bytes[sizeof(double)]; 
    ~Data(){} 
}; 

union Data var = {.x = 31293.932}; 

std::cout << var.x << "\n"; 
std::cout.write(var.bytes, sizeof(var.bytes)); 
std::cout << "\n" << var.i << "\n"; 

Полное определение того, что тип POD обширна. В очень простых терминах это базовый тип данных без явно определенного конструктора копий, деструктора или виртуальных методов и сам не содержит таких типов, если он является совокупным типом (например, struct, class и union).

+0

Рекомендовать быстрое расширение на POD (Обычные старые данные), чтобы помочь бедным новичкам. – user4581301

+0

@ user4581301 Хорошее предложение, хотя полное определение POD довольно сложно. Я добавил немного о нем, чтобы кто-то начал. –

Смежные вопросы