Прежде всего, я получаю предупреждение о том, что возвращается ссылка на локальную переменную temp
. Что не так с этим? Как это повлияет на функцию? Что мне с этим делать?
Локальная переменная, как следует из названия, является локальной для функции, которой она принадлежит, поэтому она уничтожается при возврате функции; если вы попытаетесь вернуть ссылку на него, вы вернете ссылку на то, что перестанет существовать в тот самый момент, когда функция вернется.
Хотя в некоторых случаях это может сработать в любом случае, вам просто везет, потому что стек не был перезаписан, просто вызовите какую-то другую функцию, и вы заметите, что он перестанет работать.
У вас есть два варианта: во-первых, вы можете вернуть CARD
по значению вместо ссылки; это, однако, имеет тот недостаток, что не позволяет вызывающей стороне использовать ссылку для изменения CARD
, как это хранится в vector
(это может или не может быть желательно).
Другой подход заключается в хранении статического фиктивного экземпляра CARD
в классе STACK
, который не будет иметь таких проблем при жизни, и который может быть возвращен, если у вас нет элементов в vector
; тем не менее, вы должны найти метод для «защиты» своего поля, в противном случае «глупый» вызывающий может изменить значения вашего «одиночного» фиктивного элемента, что испортит логику класса. Можно изменить CARD
на class
, который будет инкапсулировать его поля и запретит доступ на запись к ним, если это фиктивный элемент.
Что касается функции cardToString
, вы, вероятно, делаете что-то не так со строками (и я почти уверен, что вы пытаетесь вернуть локальное также и в этом случае), но не видя тела функции трудно сказать что.
Кстати, чтобы избежать многих проблем со строками, я предлагаю вместо char *
использовать класс std::string
, который устраняет большую часть уродства и низкоуровневое управление памятью у обычного char *
.
Кроме того, я бы предложил вам изменить cardToString
на const
ссылку, потому что, скорее всего, не нужно изменять объект, переданный в качестве ссылки, и хорошей практикой является четкое обозначение этого факта ( компилятор предупредит вас, если вы попытаетесь изменить такую ссылку).
<ч />
Редактировать
Функция cardToString
должна работать нормально, если с массивами RANKS
и SUITS
все в порядке. Но , если вы использовали эту функцию, как написали, вы теряете память, так как для каждого вызова cardToString
вы делаете выделение с new
, которое никогда не освобождается с delete
; таким образом, вы теряете 32 байта памяти за вызов.
Как уже говорилось ранее, мой совет - просто использовать std::string
и забыть об этих проблемах; Ваша функция становится такой простой:
std::string cardToString(const CARD& c)
{
if(c.r >= 13 || c.r < 0 || c.s >= 4 || c.s < 0)
return "(invalid card)";
return std::string(RANKS[c.r]) + " of " + SUITS[c.s];
}
И вам больше не нужно беспокоиться об утечках памяти и ее распределении.
<ч />
Для справки / значения: если вызывающей стороне не нужно использовать ссылку для изменения объекта, хранящегося в векторе, я настоятельно рекомендую передавать его по значению. Падение производительности незначительно: два int
с вместо одного указателя означают 8 против 4 байтов на большинстве 32-битных архитектур, и 8 байтов против 8 байтов на большинстве 64-битных машин (а также доступ к полям с помощью указателя требует небольших затрат) .
Этот вид микрооптимизации должен быть последним из ваших вопросов. Ваш главный приоритет - написать правильный и рабочий код, и последнее, что вы должны сделать, - это позволить микрооптимизации помешать достижению этой цели.
Затем, если у вас возникнут проблемы с производительностью, вы профилируете свое приложение, чтобы найти узкие места и оптимизировать эти критические точки.