![]() |
Здравствуйте, гость ( Вход | Регистрация )
![]() |
Litkevich Yuriy |
![]()
Сообщение
#1
|
![]() разработчик РЭА ![]() ![]() ![]() ![]() ![]() ![]() ![]() Группа: Сомодератор Сообщений: 9669 Регистрация: 9.1.2008 Из: Тюмень Пользователь №: 64 Спасибо сказали: 807 раз(а) Репутация: ![]() ![]() ![]() |
Переменные созданные внутри функций живут пока мы невышли из фукции, так вроде.
Видел такую вещь:
т.е. функция возвращает указатель на масив, который в ней же создан. Но покинув функцию масив прекратит существование и указатель будет показывать в кучу проги, например, может показывать в неосмысленное место. Я правильно понимаю, т.е. это косячек програмиста, или как-то это иначе работает применительно просто к C++? |
|
|
![]() |
archimed7592 |
![]()
Сообщение
#2
|
![]() Участник ![]() ![]() Группа: Участник Сообщений: 127 Регистрация: 27.12.2007 Из: Moscow Пользователь №: 56 Спасибо сказали: 0 раз(а) Репутация: ![]() ![]() ![]() |
Я правильно понимаю, т.е. это косячек програмиста, Угу, косячек.как-то это иначе работает применительно просто к C++? Не то чтобы. Просто, как правило, автоматические объекты хранятся на стеке и при возврате из ф-ции стек никуда не девается, но, при вызове других ф-ций(к примеру), на то место, где был этот массив будет отображена какая-нибудь другая переменная.
|
|
|
Litkevich Yuriy |
![]()
Сообщение
#3
|
![]() разработчик РЭА ![]() ![]() ![]() ![]() ![]() ![]() ![]() Группа: Сомодератор Сообщений: 9669 Регистрация: 9.1.2008 Из: Тюмень Пользователь №: 64 Спасибо сказали: 807 раз(а) Репутация: ![]() ![]() ![]() |
Т.е. если мы делаем так:
т.е. воспользовались масивом сразу, это всегда будет давать один и тот же рузультат, тогда это наормально, я правильно понял, да? |
|
|
archimed7592 |
![]()
Сообщение
#4
|
![]() Участник ![]() ![]() Группа: Участник Сообщений: 127 Регистрация: 27.12.2007 Из: Moscow Пользователь №: 56 Спасибо сказали: 0 раз(а) Репутация: ![]() ![]() ![]() |
Нет, это не гарантируется. Я тебе рассказал как это работает "в общем". Частных случаев может быть туева хуча. Грубо говоря, сегодня компилятор сделает как ты предполагал, завтра - что-нибудь где-нибудь соптимизирует и будешь вылавливать баг.
По идее нормальный компилятор должен ругнуться на такое(возвращение ссылки/указателя на локальный объект) warning'ом. |
|
|
Litkevich Yuriy |
![]()
Сообщение
#5
|
![]() разработчик РЭА ![]() ![]() ![]() ![]() ![]() ![]() ![]() Группа: Сомодератор Сообщений: 9669 Регистрация: 9.1.2008 Из: Тюмень Пользователь №: 64 Спасибо сказали: 807 раз(а) Репутация: ![]() ![]() ![]() |
понял, значит я не зря переписал этот кусок кода, в следующий вриант:
т.е. изначально надобыло получить заполненый какой либо информацией масив, заполняет некая фукция. Я переделал так чтобы функция получала указатель на масив и длину, если она по какой то причине хочет заполнять больше чем длина масива, то вернет не нуль. А было так, что функция сама формировала масив и возвращала указатель на него. Сообщение отредактировал Litkevich Yuriy - 2.2.2008, 17:07 |
|
|
archimed7592 |
![]()
Сообщение
#6
|
![]() Участник ![]() ![]() Группа: Участник Сообщений: 127 Регистрация: 27.12.2007 Из: Moscow Пользователь №: 56 Спасибо сказали: 0 раз(а) Репутация: ![]() ![]() ![]() |
Litkevich Yuriy,
А было так, что функция сама формировала масив и возвращала указатель на него. С точки зрения проектирования хорошего(удобного) интерфейса было всё правильно(кроме реализации).Я бы оставил как есть, за исключением того, что возвращал бы умный указатель(какой именно - зависит от специфики ф-ции) на динамически созданный объект(из соображений эффективности можно воспользоваться пулом для таких маленьких объектов). |
|
|
Litkevich Yuriy |
![]()
Сообщение
#7
|
![]() разработчик РЭА ![]() ![]() ![]() ![]() ![]() ![]() ![]() Группа: Сомодератор Сообщений: 9669 Регистрация: 9.1.2008 Из: Тюмень Пользователь №: 64 Спасибо сказали: 807 раз(а) Репутация: ![]() ![]() ![]() |
|
|
|
archimed7592 |
![]()
Сообщение
#8
|
![]() Участник ![]() ![]() Группа: Участник Сообщений: 127 Регистрация: 27.12.2007 Из: Moscow Пользователь №: 56 Спасибо сказали: 0 раз(а) Репутация: ![]() ![]() ![]() |
Самый примитивный пример, не требующий особых телодвижений аля скачивания boost:
Теперь если просто вызвать эту ф-цию вот так: someFunc(); то утечки не будет т.к. деструктор auto_ptr удалит объект. Называется это дело RAII(ru, en). Если хочешь подробнее об умных указателях, то почитай здесь, у Мейрса, у Александреску, у Саттера. Сообщение отредактировал archimed7592 - 2.2.2008, 20:37 |
|
|
Litkevich Yuriy |
![]()
Сообщение
#9
|
![]() разработчик РЭА ![]() ![]() ![]() ![]() ![]() ![]() ![]() Группа: Сомодератор Сообщений: 9669 Регистрация: 9.1.2008 Из: Тюмень Пользователь №: 64 Спасибо сказали: 807 раз(а) Репутация: ![]() ![]() ![]() |
|
|
|
Tonal |
![]()
Сообщение
#10
|
![]() Активный участник ![]() ![]() ![]() Группа: Участник Сообщений: 452 Регистрация: 6.12.2007 Из: Новосибирск Пользователь №: 34 Спасибо сказали: 69 раз(а) Репутация: ![]() ![]() ![]() |
А вот auto_ptr с массивом использовать не надо - убъёть!
![]() Litkevich Yuriy Проще всего переделать код на использование vector<int>. С ним твоя исходная функция будет выглядеть так:
А использовать её будешь так:
Написано об этом очень хорошо у Страуструпа в самом начале "Язык программирования С++ 3ед." - книжка, которую каждый уважающий себя программист на С++ должен прочитать и понять. ![]() |
|
|
Andrew Selivanov |
![]()
Сообщение
#11
|
![]() Участник ![]() ![]() Группа: Участник Сообщений: 249 Регистрация: 9.10.2007 Из: Москва Пользователь №: 3 Спасибо сказали: 15 раз(а) Репутация: ![]() ![]() ![]() |
А вот auto_ptr с массивом использовать не надо - убъёть! ![]() Litkevich Yuriy Проще всего переделать код на использование vector<int>. С ним твоя исходная функция будет выглядеть так:
А использовать её будешь так:
Написано об этом очень хорошо у Страуструпа в самом начале "Язык программирования С++ 3ед." - книжка, которую каждый уважающий себя программист на С++ должен прочитать и понять. ![]() Мммм... вариант, но мне кажется, что так будет несколько неудобно обрабатывать ошибку (т.е. нулевое значение при возврате), кроме того ( поправьте если ошибаюсь), из временного внутреннего вектора будет лишнее копирование. Мне кажется, корректней будет так:
Ну и typedef не забыть если это конкретный тип, или сделать сразу шаблончик из функции ![]() И еще вариант: можно вернуть итератор... |
|
|
Tonal |
![]()
Сообщение
#12
|
![]() Активный участник ![]() ![]() ![]() Группа: Участник Сообщений: 452 Регистрация: 6.12.2007 Из: Новосибирск Пользователь №: 34 Спасибо сказали: 69 раз(а) Репутация: ![]() ![]() ![]() |
Если это действительно ошибка - кидай исключение.
Если - одно из возможных значений - можно обойтись возвратом пустого вектора. Насчёт копирования - вменяемые компиляторы С++ применяют оптимизацию возвращаемого значения, так что в итоге, скомпилированный код будет очень похож на код с передачей ссылки. ![]() Хотя если не очень доверяешь компилятору - можно и руками пооптимизировать, но мне кажеться, что делать это надо только когда понятно что именно. ![]() Да, по тому, что написал автор, видно что размерчик ему известен, стал быть его сразу нужно вектору и выставить. Сообщение отредактировал Tonal - 5.2.2008, 8:37 |
|
|
Litkevich Yuriy |
![]()
Сообщение
#13
|
![]() разработчик РЭА ![]() ![]() ![]() ![]() ![]() ![]() ![]() Группа: Сомодератор Сообщений: 9669 Регистрация: 9.1.2008 Из: Тюмень Пользователь №: 64 Спасибо сказали: 807 раз(а) Репутация: ![]() ![]() ![]() |
видно что размерчик ему известен Да известен, это буфер для работы с UART'ом, собственно, некоторые функции кладут в этот буфер в определенное место свои данные, потом буфер уезжает к внешнему девайсу, максимальный размер буфера в котором ЦЕЛЫХ 28 байт (для девайса это много). |
|
|
AD |
![]()
Сообщение
#14
|
Профессионал ![]() ![]() ![]() ![]() ![]() Группа: Участник Сообщений: 2003 Регистрация: 4.2.2008 Из: S-Petersburg Пользователь №: 84 Спасибо сказали: 70 раз(а) Репутация: ![]() ![]() ![]() |
А вот auto_ptr с массивом использовать не надо - убъёть! ![]() Litkevich Yuriy Проще всего переделать код на использование vector<int>. С ним твоя исходная функция будет выглядеть так:
А использовать её будешь так:
Написано об этом очень хорошо у Страуструпа в самом начале "Язык программирования С++ 3ед." - книжка, которую каждый уважающий себя программист на С++ должен прочитать и понять. ![]() Полностью согласен с данным автором. На мой взгляд, если и делать подобное, то, как указано выше. А вообще не советовал бы возвращать указатель на локальный массив. Лучше бы завести его глобально или через namespace. |
|
|
![]() ![]() |
![]() |
|
Текстовая версия | Сейчас: 3.6.2025, 19:38 |