Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > C/C++ программирование > Общие вопросы C/C++
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 29.02.2012, 22:54   #1
LiuLiuJons
Форумчанин
 
Регистрация: 28.12.2011
Сообщений: 124
По умолчанию Функция возвращает указатель на массив

Не знаю насколько я правильно делаю.
Но идея такова: есть массив с двумя (в последствии может с тремя) элементами, хочу возвратить эти значения по средствам функции.

Объявление функции:
Код:
int *getPos(){ static int a[2]; a[0] = x[0]; a[1] = y[0]; return a;}
Вызов функции:
Код:
int *b = arr[whereMove].getPos();
Считывание первого и второго элементов:

Код:
Label5->Caption = "b1 = " + IntToStr(*b);
Label6->Caption = "b2 = " + IntToStr(*(b + 1));
Проблема в том, что порой значения b1 и b2 не обновляются. Хотела уточнить, может ли быть проблема именно в этой функции и корректно ли так возвращать указатель на массив?
"Думай не о задаче, а о решении" (с)
LiuLiuJons вне форума Ответить с цитированием
Старый 29.02.2012, 23:21   #2
_Bers
Старожил
 
Регистрация: 16.12.2011
Сообщений: 2,329
По умолчанию

1. Судя по представленному коду, значения статического массива не "порой не обновляются" потому что не изменяются значения массивов x и y, которые скармливаются статическому массиву.

2. Синтаксически корректно, правомерно.

3. Идеологически - серьёзный признак ущербной архитектуры.

4. Практически - мина замедленного действия, пороховая бочка, либо - выстрел в ногу.

Судя по тому, что у вас "что то там порой работает не так, как ожидается", выстрел в ногу уже произведен.
_Bers вне форума Ответить с цитированием
Старый 29.02.2012, 23:39   #3
LiuLiuJons
Форумчанин
 
Регистрация: 28.12.2011
Сообщений: 124
По умолчанию

Цитата:
Сообщение от _Bers Посмотреть сообщение
1. Судя по представленному коду, значения статического массива не "порой не обновляются" потому что не изменяются значения массивов x и y, которые скармливаются статическому массиву.
Да, я это проверяла и продолжаю проверять - к правильному ли элементу относятся. Но не могу поймать откуда идёт ошибка.

Цитата:
Сообщение от _Bers Посмотреть сообщение
3. Идеологически - серьёзный признак ущербной архитектуры.
"Я ещё не волшебник, я только учусь" (с) И как следствие всё криворуко и кособоко.
Подскажите, что можно использовать вместо этого, чтобы идеологию улучшить, да и ногу себе не отстрелить.
"Думай не о задаче, а о решении" (с)
LiuLiuJons вне форума Ответить с цитированием
Старый 01.03.2012, 00:11   #4
_Bers
Старожил
 
Регистрация: 16.12.2011
Сообщений: 2,329
По умолчанию

Здесь нужно понимать две вещи:
1. Принцип работы со статическими данными. А конкретно - время их жизни, и где они вообще на самом деле живут.

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

Особенность статических переменных заключается в том, что время их жизни - до конца жизни всего приложения.

Если объявить статическую переменную внутри обычной функции, то область видимости переменной будет - внутри этой функции. А время жизни - до конца приложения.

Если объявить статическую переменную внутри метода класса, то область видимости переменной будет - внутри этого метода. А время жизни - до конца приложения.

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

На самом деле, статическая переменная внутри метода будет создана только один раз, и будет "общей" для любого вызвавшего метод объекта класса.

Пример:

Первый объект толкает метод getPos(), изменяет значения статического массива, и получает на него указатель.

Потом второй объект тоже толкает метод getPos(), и таким образом, содержимое статического массива изменяется.

Потом из первого объекта по указателю извлекаются данные. Но это вовсе не те данные, которые установил этот первый. Это данные, которые установил Второй.

Второй объект воздействовал на тот же самый массив.

Итого: Первый объект выдаёт совсем не те данные, которые он устанавливал.

Вы уверены, что это именно то, что вам было нужно?

2. Здравый смысл, целесообразность конструкции.

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

Если вам действительно нужны общие для всех объектов данные-члены, объявите их статическими в самом классе, а не в отдельных его методах.

Эффект будет примерно тот же, но путаницы на порядок меньше.

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

Идеологически корректно (просто для понимания, и логично с точки зрения здравого смысла) следующее положение:

Все общее для всех экземпляров класса - статическое
Все уникальные для каждого объекта данные - мемберы

Попытка запихать в метод-мембер "общую для всех сущность" противоречит здравому смыслу. Есть лишь очень и очень мало ситуаций, где такой подход действительно может быть оправданным. И совсем не существует ситуаций, где это действительно необходимо, и где этого нельзя было бы избежать.

Резюмируя: статические переменные внутри методов класса не нужны. Они запутывают, и несут в себе потенциальную опасность.

Последний раз редактировалось _Bers; 01.03.2012 в 00:13.
_Bers вне форума Ответить с цитированием
Старый 01.03.2012, 01:00   #5
LiuLiuJons
Форумчанин
 
Регистрация: 28.12.2011
Сообщений: 124
По умолчанию

Цитата:
Сообщение от _Bers Посмотреть сообщение
Если объявить статическую переменную внутри метода класса, то область видимости переменной будет - внутри этого метода. А время жизни - до конца приложения.
Да, в принципе мне только это и надо. Этот метод я вызываю только для одного объекта данного класса и сразу записываю полученные данные.

Цитата:
Сообщение от _Bers Посмотреть сообщение
Первый объект толкает метод getPos(), изменяет значения статического массива, и получает на него указатель.

Потом второй объект тоже толкает метод getPos(), и таким образом, содержимое статического массива изменяется.

Потом из первого объекта по указателю извлекаются данные. Но это вовсе не те данные, которые установил этот первый. Это данные, которые установил Второй.

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

Впрочем такой метод используется в моей программе только раз, и я его не очень понимаю - поэтому и обратилась с вопросом корректен ли он. До этого я не применяла статические переменные.

В основном класс такой:
Цитата:
Сообщение от _Bers Посмотреть сообщение
Все уникальные для каждого объекта данные - мемберы
Параметр static используется только потому, что нужно хранить указатель на массив. Если убрать этот параметр - данные будут пропадать сразу и такой метод с возвращением указателя на массив использовать будет нельзя в моём случае.
Сделаю без указателей и массивов.

Спасибо за подробное разъяснение.
"Думай не о задаче, а о решении" (с)
LiuLiuJons вне форума Ответить с цитированием
Старый 01.03.2012, 01:10   #6
_Bers
Старожил
 
Регистрация: 16.12.2011
Сообщений: 2,329
По умолчанию

Цитата:
Сообщение от LiuLiuJons Посмотреть сообщение
Да, в принципе мне только это и надо. Этот метод я вызываю только для одного объекта данного класса и сразу записываю полученные данные.
В таком случае, нужно видеть весь код, что бы понять, как портятся данные.
Подозрение - данные в массивах x и y остаются без изменений. Поэтому, в a значения и не меняются (в него попадают одни и те же значения).

Но что бы знать точно - нужно видеть код.
_Bers вне форума Ответить с цитированием
Старый 01.03.2012, 01:32   #7
LiuLiuJons
Форумчанин
 
Регистрация: 28.12.2011
Сообщений: 124
По умолчанию

Ну код там страшный и запутанный на самом деле. x и y меняются, но не всегда. Скорее всего я намудрила в этих условиях, впрочем в приложении 3 нужных файла.
Оговоренный метод используется в процедуре Move()
Вложения
Тип файла: rar files.rar (5.0 Кб, 9 просмотров)
"Думай не о задаче, а о решении" (с)
LiuLiuJons вне форума Ответить с цитированием
Старый 01.03.2012, 02:15   #8
_Bers
Старожил
 
Регистрация: 16.12.2011
Сообщений: 2,329
По умолчанию

Похоже, что вы пишете в си билдере. У меня нет этой ИДЕ, посему я просто внешне глянул код. Смотрите:

Вот это строки из метода move()
Код:
        int *b = arr[whereMove].getPos();

	Label5->Caption = "b1 = " + IntToStr(*b);
	Label6->Caption = "b2 = " + IntToStr(*(b + 1));
Обратите внимание: getPos() толкает объект, который является элементом массива arr.

Теперь смотрим, что за массив такой, и кто там живет:

Код:
Field* arr = new Field[amount]; // main field inicializing
Здесь выделяется целый блок, способный вместить в себя amount элементов.
Смотрим, сколько там живет зверей:

Код:
int c = 3, r = 5, z = 0; // column, row count for main field
int amount = r * c; // total amount of cells in the field
15 элементов. Каждый из которых теоретически может толкнуть метод getPos()

Теперь возвращаемся на исходную:

Код:
int *b = arr[whereMove].getPos();
Конкретно, метод толкает элемент с индексом whereMove
Смотрим, где выше по тексту он может изменится:

Он у вас может менятся, как выше по тексту:

Код:
switch(arr[currentF].getState()) {
	case true: {
			return;
		}
	case false: {
			whereMove = currentF;
			s++;
			break;
		}
	default: {
			return;
		};
	}
Так и ниже:

Код:
whereMove = 0;
И судя по всему, зависит от состояния других компонентов системы:
Код:
switch(arr[currentF].isMain())
Все это наводит на предположение о том, что ваше утверждение:
Этот метод я вызываю только для одного объекта данного класса и сразу записываю полученные данные.


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

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

Если вы не умеете выполнять пошаговую отладку - тогда попробуйте вести лог:
Вам понадобится какой нибудь виджет, в который можно выводить сообщение.
Что-то типа вот такого:
Код:
// where we move
	Label3->Caption = "whereMove = " + IntToStr(whereMove);
Выводите туда какой именно элемент толкает метод. То бишь, его индекс, и значения, которые запишутся в массив. Тогда сможете поймать тот момент, когда это делает тот, кому это делать не положено.

/зы: не увидел в коде самого класса статического массива. А так же какой бы то ни было в нем необходимости.

Последний раз редактировалось _Bers; 01.03.2012 в 02:20.
_Bers вне форума Ответить с цитированием
Старый 01.03.2012, 15:48   #9
LiuLiuJons
Форумчанин
 
Регистрация: 28.12.2011
Сообщений: 124
По умолчанию

Цитата:
Сообщение от _Bers Посмотреть сообщение
Все это наводит на предположение о том, что ваше утверждение:
Этот метод я вызываю только для одного объекта данного класса и сразу записываю полученные данные.


Как минимум требует точной проверки. Теоретически, в вашем коде возможна ситуация, что метод getPos() толкают разные объекты класса.
Да, действительно, толкают разные объекты класса, я неправильно думала.
Но все проверки у меня как раз и есть, я же вывожу:
Код:
	int *b = arr[whereMove].getPos();
	// where we move
	Label3->Caption = "whereMove = " + IntToStr(whereMove); //индекс этого элемента
        Label5->Caption = "b1 = " + IntToStr(*b); // первый элемент массива
	Label6->Caption = "b2 = " + IntToStr(*(b + 1)); //второй элемент массива
И в следующий раз, когда нужно будет узнать позицию - я опять вызываю этот метод. При этом на данный момент мне всё равно, где находятся остальные объекты и меня интересует именно изменённое содержимое b для конкретного объекта.
"Думай не о задаче, а о решении" (с)
LiuLiuJons вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Функция возвращает неправильный указатель RomanA Общие вопросы C/C++ 3 25.02.2012 19:06
Функция возвращает массив Рик Общие вопросы Delphi 5 22.03.2011 09:07
Функция Pos возвращает 0 gufon Общие вопросы Delphi 16 14.03.2011 22:10
Функция которая возвращает динамический массив gagarin0 Помощь студентам 5 19.01.2011 13:48
функция не возвращает нужный мне массив LOST94 Общие вопросы C/C++ 0 01.07.2010 15:33