2016-11-15 1 views
0

Я пытаюсь сделать void*, чтобы сохранить значение (чтобы избежать вызова конструктора по умолчанию).Как использовать void * как единственный держатель переменной? (Пример. Void * raw = SomeClass())

Я хочу: -

  • копия K опорожнить * например, K k1; --> void* raw=k1;
  • копия void * to K eg.g. void* raw; --> K k2=raw;
  • стараются не нарушать деструктор и вызывает утечку памяти
  • не использовать любое динамическое распределение (кучи, причина производительности)

Вот что я пробовал: -

class K{ 
    public: std::string yes="yes" ; 
}; 

int main() { 
    //objective: k1->raw->k2 , then delete "raw" 
    void* raw[sizeof(K)];  //<--- try to avoid heap allocation 
    K k1; 
    static_cast<K>(raw)=k1;  //<--- compile fail 
    K k2= static_cast<K>(raw); 
    std::cout<<k2.yes;   //test 
    static_cast<K&>(raw)::~K(); //mimic destructor 
    return 0; 
} 

Вопрос: Просьба представить действительный код, который показывает правильный способ сделать это.

Я нашел, как использовать размещение new (https://stackoverflow.com/a/4756306/3577745), но не нашел, как использовать void* для переменной, которая не является массивом.

C++ - новый для меня.

Edit:
Я пишу очень пользовательский набор (массив).
Каждый элемент инкапсулирован в пользовательскую структуру KCap kcap (с удержанием только 1 элемент, то есть K).
Таким образом, я должен объявить K k в качестве поля инкапсулятора KCap.
Однако, я хочу, чтобы избежать конструктора по умолчанию K, поэтому я думаю, void* может решить мою проблему.

+1

Это пахнет, как будто у вас есть еще одна проблема, которую вы думаете * это * решит. Так почему бы не спросить об этом * вместо этого? – StoryTeller

+0

Переменная 'raw' - это * массив * указателей, а не один нетипизированный объект. Для этого нужен массив 'char', а также размещение' new'. –

+0

То, что вы пытаетесь сделать, не имеет смысла. «Void *» используется для хранения произвольного типа указателя, а не для любого другого объекта. – davmac

ответ

3

То, что вы пытаетесь сделать, не имеет смысла. Void * используется для хранения произвольного типа указателя, а не для любого другого объекта. Если вы хотите использовать хранилище для произвольного типа объекта, используйте char[].

Другие проблемы с вашим кодом включают в себя, что вам нужно, чтобы обеспечить правильное выравнивание исходного хранения, использование reinterpret_cast в ссылку, а не static_cast к неэталонному, ваш синтаксису деструктора вызова на месте не так, и что вы не 'построить объект K в "сыром" хранилище. Вот скорректированная версия:

#include <string> 
#include <iostream> 

class K{ 
    public: std::string yes="yes" ; 
}; 

int main() { 
    //objective: k1->raw->k2 , then delete "raw" 
    alignas(alignof(K)) char raw[sizeof(K)];  //<--- try to avoid heap allocation 
    K k1; 
    new (reinterpret_cast<K *>(&raw)) K(k1);  //<--- compile now succeeds :) 
    K k2= reinterpret_cast<K &>(raw); 
    std::cout << k2.yes << std::endl;   //test 
    reinterpret_cast<K&>(raw).K::~K(); // call destructor 
    return 0; 
} 
+0

Вы должны удалить комментарий компиляции с ошибкой ;-). Если это не сработает. # –

+0

@ davmac Считаете ли вы, что ответ (аналогичный вашему) в другом вопросе http://stackoverflow.com/a/15343/3577745 страдает упомянутой проблемой выравнивания? – javaLover

+1

@ javaLover Я _think_, потому что он выделяет хранилище 'char', используя' new', это нормально; то есть, что 'new' выделяет хранилище, соответствующим образом выровненное для любого объекта. Но я не совсем уверен, тбх. – davmac

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