Семантика new
в Java и C++ на самом деле очень похожа. В обоих языках, высказывания типа
Object o = new Object(); // Java
или
Object * optr = new Object(); // C++
- выделить память (на свободном магазине) достаточно большой, чтобы держать объект типа
Object
- вызвать конструктор
Object
проходящее его указатель на вновь выделенную память как указатель this
.
В Java еще немного волшебства происходит за вашей спиной, но давайте отложим это на время.
Семантика для встроенных типов (примитивы на Java) также не сильно отличается.
В Java
int[] array = new int[42];
выделяет память достаточно большой, чтобы держать 42 int
с и инициализирует их с 0.
В C++
int * array = new int[42]; // not value-initialized
также выделяет (на свободном складе) смежный достаточно большой памяти для хранения 42 int
s, но не инициализирует их. Если вы хотите инициализировать инициализацию значения, скажем так явно:
int * array = new int[42](); // initialized to 0
Наибольшая разница, возможно, в использовании этих операторов. В Java, если мы хотим новый объект, у нас нет шансов, но вызывается (возможно, через некоторую косвенность с помощью заводского метода) new
. В C++ мы можем не только создавать объекты в свободном хранилище (куче), но и с так называемой автоматической продолжительностью хранения (т. Е. Нажимать их на стек). В Java это возможно только с примитивными типами.
int i = 7; // valid in both languages
std::string name("Mona Lisa"); // valid C++, invalid Java
Часто, это то, что вы должны делать на C++. Это распространенная ошибка программистов, которые привыкли к Java и изучают C++ для использования new
повсюду, где это действительно не нужно.
Наконец, поскольку C++ по умолчанию не имеет сборщика мусора, если вы выделяете память из бесплатного хранилища (с использованием оператора new
), вы также должны снова освободить его (используя оператор delete
), как только вам это понадобится.
Почему new
и delete
называются операторами? Я не знаю. Это действительно имеет значение? Я думаю, что это имеет смысл, тем более, что вы можете перегружать их так же, как оператор +
или -
.
Синтаксис создания объекта в C++ был немного беспорядочным. Все это (иногда) действительно, но выглядит совершенно по-разному:
// automatic storage
int a = 7;
std::string name; // default constructor
std::string name("Mona Lisa");
// free store (bad idea in this case)
std::string * nameptr = new std::string(); // default constructor
std::string * nameptr = new std::string("Mona Lisa");
Есть ряд правил, о которых из этих нотаций действуют в каком контексте, и если вы забыли, некоторые довольно странные сюрпризы могут произойти.
Поскольку C++ 11, мы имеем единый синтаксис для создания объекта с использованием инициализатора списки:
// automatic storage
int a {7};
std::string name {} // default constructor
std::string name {"Mona Lisa"};
// free store (bad idea in this case)
std::string * nameptr = new std::string {}; // default constructor
std::string * nameptr = new std::string {"Mona Lisa"};
К сожалению, так как старый синтаксис остается в силе, мы имеем теперь еще больше вариантов.
Даже в java вы используете операторы, которые не являются математическими операторами, как индексный оператор '[]'. – JBL
Потому что правила говорят, что это, конец истории. '+' позволяет вам добавлять, '-' позволяет вычесть,' delete' позволяет уничтожить, а 'new' позволяет вам создавать. Каждый из этих 4 обеспечивает операцию над объектом данных, следовательно, оператор имени. – enhzflep
@JBL Я забыл, что это действительно существовало, вы были правы. –