Является ли инициализация с помощью указателей экземпляра класса единственной в C ++?

Мы все знаем, что самый простой способ определить новый экземпляр в C ++ заключается в следующем:

ClassName *obj = new ClassName();

Но такой способ плох, и более продвинутые люди используют умные указатели, такие как: shared_ptr, unique_ptr и т.д … Но если посмотреть на их источники, вы можете обнаружить, что smart_pointers используют указатели для создания новых экземпляров, а не ссылок.

Также я знаю, что использование указателей не только плохо для чистого исходного кода на C ++ (правила проектирования), но и указатели выделяют новую память, потому что любой указатель является void* тип. Правильный размер зависит от архитектуры процессора, но для примера возьмем x86, он содержит 4 байта.

Это довольно дорого, чем использовать ссылки &, которые не требуют никакого выделения памяти для них, и поэтому использовать ссылки в самоопределенных методах C ++ намного лучше.

Так что рассказывая вам всю эту информацию, мне интересно:

Можно ли определить новый экземпляр со ссылкой на C ++ или нет? Если нет, то почему?

0

Решение

Боюсь, ваш пост — одно заблуждение за другим. Итак, первое, что вам нужно сделать, это выбросить все «книги», которые вы прочитали и прочитали хорошая книга по C ++

Теперь попробуем ответить на ваш вопрос. Вы не можете создать объект «со ссылкой». Это наоборот — вы можете создать ссылку на существующий объект.

MyClass myobject;
MyClass& myreference = myobject;

Также как вы можете создать указатель для указания на существующий объект (или не указывать на что-либо). Обратите внимание, что не указатель создал объект. Новое выражение делает:

new MyClass;

создал новый объект типа MyClass «в кучу», если хотите. Но это совершенно бесполезно, так как вы потеряли все ручки к нему. Вы не можете получить к нему доступ. Вот почему мы храним адрес этого объекта (который возвращает новый) в указателе. Если это умный указатель, а не простой, он автоматически «узнает», когда освободить память, то есть удалить объект, в зависимости от типа умного указателя. При этом вы можете вместо сохранения адреса вновь созданного объекта создать ссылку на него:

MyClass& ref = *new MyClass;
...
delete &ref;

Также неверно, что ссылки приходят бесплатно (с точки зрения памяти). Конечно, sizeof (reference) будет возвращать размер упомянутого объекта, но большинство реализаций будет использовать логику, подобную указателю, для ссылок под капотом.

4

Другие решения

Мы все знаем, что самый простой способ определить новый экземпляр в C ++ заключается в следующем:

Нет! Самый простой способ создать экземпляр:

ClassName obj;

Для инициализации ссылки просто скажите:

ClassName& objRef = obj;

или же

const ClassName& constObjRef = obj;

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

1

Я думаю, что стоит исправить разные неправильные утверждения в вашем посте (в дополнение к ответу на главный вопрос), чтобы вы могли вернуться на правильный путь.

Самый простой способ определить новый экземпляр: A * a = new A();

Нет, самый простой способ A a;

Такой способ плох, поэтому более продвинутые люди используют умные указатели

Действительно, это не самый рекомендуемый. Основными недостатками являются:

  1. Объекты размещаются в куче, что замедляет доступ.

  2. Вы должны управлять памятью самостоятельно, позвонив delete явно.

Использование умных указателей решает только пункт 2. Вот почему более продвинутые люди фактически использовали бы как можно больше распределения в стеке, используя A a;, Однако это не всегда возможно, в таком случае умный указатель действительно является лучшим вариантом.

Но умные указатели используют указатели, а не ссылки!

Действительно, точка умного указателя только чтобы помочь с управлением памятью (вот почему заголовок #include <memory>), поэтому они имеют дело с объектами в куче, а не в стеке. То, что они делают, зовет delete для вас, так что вам не нужно беспокоиться об утечке памяти.

Указатели плохие, потому что любой указатель относится к типу void *, который занимает память

Да, указатель занимает в стеке N бит памяти (N = 32 или 64 в зависимости от вашей архитектуры) + фактический размер S объекта в куче. Но это также верно для ссылок! Краткое изложение пространства, необходимого для различных типов объектов:

  • указатели (A * a = new A;): N бит в стеке (адрес) + S бит в куче (объект)

  • Рекомендации (A a; A &ref = a;): N бит в стеке (адрес) + S бит в стеке (объект)

  • Прямые ценности (A a;): S бит в стеке (объект)

Таким образом, с точки зрения пространства памяти, ссылки и указатели одинаковы, вы получите только выигрыш, если будете использовать прямые значения в стеке. Обратите внимание, что на самом деле ссылка также может указывать на объект в куче (A &ref = *new A;) и указатель также может указывать на объект в стеке (A a; A * ptr = &a;).

Можно ли определить новый экземпляр со ссылкой на C ++ или нет?

Да:

A a;
A &ref = a;
1

Мы все знаем, что самый простой способ определить новый экземпляр в C ++ заключается в следующем:

ClassName *obj = new ClassName();

Нет, мы не … потому что это не так.

Чтобы создать новый экземпляр типа ClassName, просто напишите:

ClassName obj;

Использовать только динамическое распределение когда вам нужно!

Но такой способ плох, и более продвинутые люди используют умные указатели, такие как: shared_ptr, unique_ptr и т. Д. Но если посмотреть на их источники, вы можете обнаружить, что smart_pointers используют указатели для создания новых экземпляров, а не ссылок. Также я знаю, что использование указателей — это не только плохая вещь для чистого исходного кода на C ++ (правила разработки)

Какие правила дизайна? Здесь нет «правил», только разные наборы методические рекомендации написано разными людьми, все со своими взглядами.

я было бы обычно советуют избегать использования указателей, поскольку их использование подразумевает динамическое распределение, которым сложнее управлять. Умные указатели помогают в этом, но они не являются причиной для использования динамического размещения, в противном случае вы бы этого не сделали.

также указатели выделяют новую память, потому что любой указатель имеет тип void *. Правильный размер зависит от архитектуры процессора, но для примера возьмем x86, он содержит 4 байта.

Ну, это тоже не правда. Каждый тип указателя имеет свой собственный тип, и они не обязательно имеют одинаковую ширину. Обычно, однако, это может иметь место.

Это довольно дорого, чем использовать ссылки &, которые не требуют никакого выделения памяти для них, и поэтому использовать ссылки в самоопределенных методах C ++ намного лучше.

Нет, тоже не правда. Ссылочный синтаксис в C ++ шкуры разыменовывать операции, выполняя их прозрачно, но вы обнаружите, что все реализации / цепочки инструментов / компиляторы реализуют ссылки с использованием указателей в любом случае.

Вы должны перестать думать о «указатели» против «ссылки». Возможно, вы думаете о Java.

Вы должны думать о продолжительность автоматического хранения («стек») против продолжительность динамического хранения («куча») — бывший является более эффективно, так как не требует динамические распределения, но вы теряете способность точно контролировать время жизни вашего объекта.

Можно ли определить новый экземпляр со ссылкой на C ++ или нет? Если нет, то почему?

Если под этим вы подразумеваете «как создать объект без динамического выделения», обратитесь к приведенному ниже примеру:

// automatic storage duration - cheap!
ClassName obj;

// dynamic storage duration - marginally more expensive,
// and now you have to `delete` it, too
ClassName* ptr = new ClassName;

В C ++ ссылка похожа на «автоматический указатель»; он выполняет ту же работу, но без всех требований синтаксиса:

ClassName* ptr = &obj;  // a pointer to obj
ClassName& ref = obj;   // a reference to obj

new Оператор всегда дает вам указатель на динамически размещенный объект, а не ссылку. Это просто так.

1
ClassName *obj = new ClassName();

Это не самый простой способ. Это :

ClassName obj;

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

ClassName obj;
ClassName& refObj = obj;

Ссылки, которые вы хотите использовать, не могут быть созданы без объекта, на который можно ссылаться.

1

возвращаться по ссылке в C ++ не очень хорошая идея (я думаю, вы имели в виду это). Потому что вы не можете вернуть локальные переменные в функцию по ссылке. ссылаясь на ссылка на сайт:

int& DoubleValue(int nX)
{
int nValue = nX * 2;
return nValue; // return a reference to nValue here
} // nValue goes out of scope here

«… Функция пытается вернуть ссылку на значение, которое выйдет из области видимости, когда функция вернется. Это будет означать, что вызывающая сторона получает ссылку на мусор …»

0