2012-07-03 3 views
1

Возможно ли передать некоторые параметры конструктору класса внутри конструктора другого класса, используя malloc? Я могу сделать это с new. Мне нужно сделать то же самое с malloc: (Если это не имеет смысла, считает, что я использую пользовательский аллокатор вместо таНоса)malloc и конструкторы в C++

Class A_Class ... { 
     public: 
     B_Class *b; 
... 
    A_Class: ... 
     { b = new B_Class (c1, c2, c3); 
     } // end of constructor 
} 

Теперь таНос:

Class A_Class ... { 
     public: 
     B_Class *b; 
... 
    A_Class: ... 
     { b = (B_Class*) malloc (sizeof(*b)); 
     ??????????????? } 
} 
+1

* б = B_Class (c1, c2, c3); –

+1

Зачем вам нужно 'malloc' над' new'? –

+0

На самом деле это пользовательский распределитель. Я использовал «malloc», чтобы сделать вопрос более разумным. –

ответ

9

malloc выделяет необработанную память. Нет смысла пытаться передать ему аргументы конструктора, потому что он не вызывает никаких конструкторов.

Если вы должны работать с сырой памятью, это до вас, чтобы построить объект в ранее выделенной сырым памяти с помощью «placement new» Синтаксис

... 
void *raw_b = malloc(sizeof *b); 
b = new(raw_b) B_Class(c1, c2, c3); // <- placement new 
... 

Числены значение b будет таким же как raw_b, т.е. можно обойтись без дополнительного указателя raw_b. Но я предпочитаю делать это таким образом, с промежуточным указателем void *, чтобы избежать уродливых бросков.

Будьте осторожны при уничтожении таких объектов, конечно. Для пользовательского выделения требуется выборочное удаление. Вы не можете просто delete ваш b в общем случае. Симметричная последовательность выборочного удаления включала бы явный вызов деструктора с последующим освобождением памяти.

b->~B_Class(); // <- explicit destructor call 
free(b); 

P.S. Вы могли бы пойти по другому пути: перегрузите operator new/operator delete в свой класс, вместо того чтобы четко указывать произвольное распределение каждый раз, когда вам нужно создать объект.

+0

Спасибо, Андрей. Разве он не выделяет новую память для raw_b? Вы уверены, что таким образом raw_b использует память, выделенную в первой строке? –

+0

@Amir Reza: Да, это весь смысл этой стандартной функции. Эта конкретная форма размещения new делает именно то, что: создает объект в данном месте в предварительно выделенной памяти. – AnT

+1

Помимо исключения прикладов, другое преимущество указателя 'void *' заключается в том, что если вы получите свой 'B_Class *' из результата 'new', то вы не сможете увлечься, думая, что ваш указатель на B_Class указывает на фактический объект 'B_Class', прежде чем он действительно это сделает. –

0

malloc не вызывает конструкторы. Невозможно передать параметры функции, которая не вызвана. Что касается пользовательского распределителя, вам нужно быть более конкретным относительно того, что вы делаете. Кто выделяет, где использовать пользовательский распределитель. Обычно пользовательские распределители используются только для распределения; они также не связаны с конструктором.

+0

Спасибо Джеймсу. Конечно, он не вызывает конструкторы. Но почему я не могу передать параметры после выделения памяти? что-то вроде того, что делает «новое». –

+0

Потому что вы не вызываете какой-либо конструктор, даже после выделения памяти. Единственный способ передать параметры конструктору - это новый оператор. (Возможно, размещение нового, если вы выделили выделение из инициализации. Или с помощью настраиваемого оператора new.) –

2

Нет, это невозможно. Если он предназначен для C++, то ваш пользовательский распределитель будет иметь функцию с именем construct, которая используется для этого (и rebind, чтобы получить распределитель, который может построить другой тип).

В C++ 03 это только копирование, поэтому вам нужно будет позвонить allocator.construct(ptr, B_Class(c1, c2, c3)), и класс должен быть скопирован. В C++ 11, распределители могут строить из любых аргументов.

Если ваш распределитель предназначен для C, вам придется использовать так называемое «размещение нового». Конечно, malloc предназначен для C. Вы должны искать его для себя, но синтаксис:

b = (B_Class*) malloc(sizeof(*b)); 
new ((void*)b) B_Class(c1,c2,c3); 

Не забудьте обработать любое исключение, что конструктор может бросить и free буфер.

+0

вам может понадобиться '#include ' для размещения нового – Pierre

+0

@Pierre: true. Одна из причин, по которой я говорю: «Посмотрите сами», заключается в том, что я использую его так невероятно редко, что сам не могу запомнить детали. И у меня есть преимущество перед вопрошающим, что я слышал об этом! –

+0

просто комментируя не волнуйтесь :) – Pierre

0

Вы можете создать статический метод для построения B:

class B_Class 
{ 
    public static B_Class* MallocMe(SomeParam param) 
    { 
      B_Class* retval = (B_Class*) malloc(sizeof(B_Class)); 
      retval->Construct(param); 
      return retval; 
    } 
.... 
Смежные вопросы