Вызывает ли new
в C++ конструктор за кулисами? Или это наоборот?
Я видел такой код, как new MyClass(*this)
, который меня смущает, так как я не знал, что new
может принимать аргументы.
Может быть, это потому, что new
может вызвать конструктор и, как следствие, может принимать аргументы, объявленные конструктором?
Хотя это неплохой вопрос, это признак того, что вам нужна хорошая книга по C++. Конструктор может принимать все виды аргументов. Почему вы думаете иначе? Как еще std::string
строится с уже существующим значением?
@NathanOliver, о да. это просто аргумент конструктора
new MyClass(*this)
вызывает конструктор, вы передаете аргументы конструктору, а не самому new
.
Посмотрите на cppreference (2)
Выражение new MyClass(*this)
действительно приводит к вызову конструктора, при условии, что память для объекта была успешной. Это не отличается от выражения new MyClass
; последний просто использует конструктор, который работает без указания каких-либо аргументов конструктора...
Это не new
аргументы, это конструктор принимает аргументы.
Возможно, вам потребуется добавить учебник о разнице между новым выражением и новым оператором.
MyClass(*this)
создает объект типа MyClass
, вызывая его конструктор и передавая *this
в качестве аргумента. Помещение new
за ним означает, что объект размещается в куче, а не в стеке. Не new
принимает аргумент, а MyClass
.
Есть разница между new
и operator new
.
Оператор new
использует скрытую функцию operator new
для выделения памяти, а затем также «инициализирует значение» объекта, вызывая его конструктор с параметрами после имени класса.
В вашем случае вы вызываете new
, который выделяет память с помощью ::operator new()
, а затем инициализирует объект класса MyClass
в этой памяти, используя конструктор с параметром *this
.
#include <iostream>
class A {
public:
int m_value;
A(int value): m_value(value){};
};
int main (){
int *a = new int;
auto b= new A(1);
std::cout << *a << std::endl;
std::cout << b->m_value << std::endl;
printf("%02x ", *b);
}
Program returned:
0
15
0f
Как видите, new
для переменной a
создает только указатель, который инициализируется значением до 0. Вот почему, когда мы разыменовываем его, мы получаем 0 (все биты все 0, int большую часть времени занимает 4 байта, а точка указателя до содержимого памяти = до 0x0000)
Но для переменной b
мы передаем параметры. И если мы посмотрим на содержимое памяти объекта b
, мы сможем прочитать 0f
, что означает, что он содержит 15 (значение члена)
Я подозреваю, что путаница OP происходит из-за осознания того, что operator new
можно переопределить. Возможно, стоит отметить, что оператор new
вызывает operator new
, а затем вызывает конструктор для этой памяти.
Спасибо! @MooingDuck Я только что обновил фрагмент кода тем, что, как я понял, вы имели в виду. Пожалуйста, дайте мне знать, если вы думаете, что это неправильно!
@Josh: я переформулировал ответ, чтобы, надеюсь, ответить на вопрос, не слишком углубляясь в загадочные подробности того, что такое инициализация значений или как работает переопределение operator new
. Neofelis: Мне не нравится, что я внес столько изменений в твой пост, но, видимо, Джош все еще был в замешательстве. Я надеюсь, что правки в порядке.
Для тех, кому интересно, это предлагает немного больше информации о переопределении operator new
: coliru.stacked-crooked.com/a/897bc134e2cc56f0 Это интересно, но обычно бессмысленно, и лучше избегать этого загадочного уголка C++.
Для любопытных этот ответ предлагает немного больше информации о том, как предоставить параметры самому operator new
: stackoverflow.com/questions/34800940/parameters-to-operator-new. tldr дополнительные параметры идут между new
и именем класса. A* p = new("new-parameter") A("A-ctor-parameter");
«int в большинстве случаев 4 бита» << нет, это 4 или 8 байтов, то есть 32 или 64 бита большую часть времени. также 0x0000
будет 2 байта / 16 бит (один полубайт имеет длину 4 бита или полбайта, и вы помещаете здесь четыре полубайта)
Не беспокойтесь, ваши изменения были полезны. И вам удалось сохранить ответ «упрощение», чтобы не запутаться в деталях. Кстати, Джош, кажется, понял, потому что никаких новых хороших новостей
CherryDT, Извините, слова байты в моем языке не существует и я все перепутал.
@appleapple Это не новое размещение