2014-09-15 3 views
4

Я действительно прихожу из Java, поэтому у меня немного путаница в изучении C++.Уточнение: что делает «новым» оператором в C++

Одна вещь, которую я видел, - это то, что во многих учебниках описывается new как оператор. В Java я обычно использую это ключевое слово для создания экземпляров классов, т. Е. Создания объектов из этого класса.

MyObject mo = new MyObject(); 

Я знал, что он также может быть использован для выделения динамической памяти, как и с int* a = new int;, но я не получаю, почему это называется оператором. Я полагаю, что операторы являются символами, которые используются для выполнения математических операций, которые тоже находятся между операндами. Тем не менее, новое не используется между операндами, в соответствии с моим основным пониманием.

Может ли кто-нибудь объяснить мне, почему это называется оператором?

Спасибо.

+0

Даже в java вы используете операторы, которые не являются математическими операторами, как индексный оператор '[]'. – JBL

+2

Потому что правила говорят, что это, конец истории. '+' позволяет вам добавлять, '-' позволяет вычесть,' delete' позволяет уничтожить, а 'new' позволяет вам создавать. Каждый из этих 4 обеспечивает операцию над объектом данных, следовательно, оператор имени. – enhzflep

+0

@JBL Я забыл, что это действительно существовало, вы были правы. –

ответ

4

Я придерживаюсь мнения, что операторы являются символами, которые используются для выполнения математических операций, что тоже, между операндами

Это верно только бинарных операторов инфиксные. Существуют также унарные операторы, которые принимают один операнд (числовое отрицание, логическое отрицание), операторы постфикса в скобках (квадратные скобки, круглые скобки) и скопированные операторы префикса (конверсия) в C++.

Учитывая такое множество операторов на C++, неудивительно, что new также является оператором. Это оператор ключевого слова prefix, который работает с именем типа и создает указатель на экземпляр этого типа. Оператор также имеет несколько форм: помимо обычного new, имеется оператор размещения new, который имеет несколько иной синтаксис.

+2

Почему? Что делает его оператор-иш? Просто сказать, что «стандарт» может работать, хотя и имеет ощущение откоса ... – Deduplicator

+0

Спасибо за ваш ответ, он разъясняет меня как новичок на этом языке. –

0

Что значит быть оператором? В языках программирования operators являются конструкциями, которые ведут себя как функции, но семантически или синтаксически отличаются от обычных функций.

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

new отвечает всем этим требованиям.

+1

Что означает «вести себя как функции», если ни синтаксис, ни семантика не совпадают? –

+0

@BenVoigt Да, эта формулировка, безусловно, плохая. Предполагается, что «Behave like functions» означает, что комбинация имени и набора аргументов дает некоторые результаты. Они не подчиняются общим правилам синтаксиса функций, и их семантика отличается от перегрузки. – pmr

+0

функции также могут быть перегружены. Это не особая особенность только операторов. Фактически, некоторые операторы, такие как оператор '&&', ведут себя более функционально, как если они перегружены (в случае && он теряет способность к короткому замыканию). – YoungJohn

1

Из-за различия между примитивами и объектами в C++ «оператор» имеет два значения. Первое значение близко к тому, что вы описываете в своем вопросе: операторы выполняют определенную операцию по их примитивным аргументам, таким как добавление или распределение памяти, как определено стандартом.

Но при использовании с объектами операторы работают совершенно по-другому: они называют свою соответствующую функцию-член класса. Например, !, который выполняет логическое отрицание примитивов, вызывает функцию объекта bool operator !(). Файловые потоки в C++ переопределяют функцию !, чтобы проверить, произошла ли ошибка в потоке.

new является оператором, потому что аналогично calls a member function (и может быть переопределен! Хотя я никогда не видел, чтобы кто-то это делал).

0

C++ - это не Java. В Java-операторы нельзя перегружать.

В C++ они могут и есть синтаксис для этого. Чтобы перегрузить new в C++, вы используете перед этим слово operator. Существует также operator new[], который может быть перегружен.

Я предполагаю, что он выделяется как не функция, даже если он может выглядеть как один, т. Е. Он принимает аргументы размера и возвращает void *.

Вы можете перегрузить классный элемент new и delete, а также new[] и delete[]. (Strangely operator new для класса по-прежнему принимает в качестве аргумента количество байтов, что кажется странным, поскольку оно должно быть размером класса, поэтому вы можете подумать, что это может быть подразумевается).

1

Семантика 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"}; 

К сожалению, так как старый синтаксис остается в силе, мы имеем теперь еще больше вариантов.

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