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

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

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

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

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

Ответ
 
Опции темы Поиск в этой теме
Старый 14.10.2017, 09:14   #11
alexzk
Форумчанин
 
Регистрация: 12.04.2017
Сообщений: 889
По умолчанию

Цитата:
Сообщение от Croessmah Посмотреть сообщение
Если посмотреть код в первом сообщении, то там да. )))
Любитель сдвига вместо умножения на два.
Кстати да, где-то встречал, что это эффективно, только на интелах. На других процах умножать быстрее, в итоге - лучше позволить компилятору решить, какой ассемблер делать. Хотя, думаю, сдвиг он тоже заменить умножением, если нужно.
А еще мне while режит глаз, в С/С++ предпочтительнее for во всех случаях. Точнее, его синтаксис позволяет только его использовать.
alexzk вне форума Ответить с цитированием
Старый 14.10.2017, 09:37   #12
Croessmah
Вредный кошак
Участник клуба
 
Аватар для Croessmah
 
Регистрация: 14.10.2012
Сообщений: 1,159
По умолчанию

Немного о оптимизациях: https://habrahabr.ru/post/339962/
Croessmah вне форума Ответить с цитированием
Старый 14.10.2017, 15:09   #13
Haric_110
Форумчанин
 
Регистрация: 03.03.2013
Сообщений: 102
По умолчанию

Цитата:
Сообщение от Croessmah Посмотреть сообщение
Если посмотреть код в первом сообщении, то там да. )))
Любитель сдвига вместо умножения на два.
Я решаю задачи, которые имеют высокие требования к эффективности алгоритма, и сталкивался ни раз со случаем, когда сдвиговые операции значительно уменьшали время выполнения. Это целесообразно использовать в циклах, конечно, а не в единичных операциях, но я взял такой стиль, не придирайтесь к нему)

Цитата:
Сообщение от Croessmah Посмотреть сообщение
Для начала:
Код:
//while (ind_2 < n) i[ind_2] = ind_2++;
while (ind_2 < n) {
   i[ind_2] = ind_2;
   ++ind_2;
}
А дальше посмотрим.
Одно и тоже. В этой части кода ошибки нет.

Цитата:
Сообщение от alexzk Посмотреть сообщение
Двумерный массив - это массив указателей на указатели.


Код:
char **strings = new char *[n];
for (int i = 0; i < n; ++i)
strings[i] = new char[m];

Код:
for (int i = 0; i < n; ++i)
   delete [] strings[i];
delete [] strings;
В таком варианте работать с ним, как strings[i][j]

Но такое делают достаточно редко, чаще выделяют 1-мерный массив размера m * n, и работают типа *(string + i *n +j) через арифметику указателей. В таком варианте, память под данные будет в непрерывном блоке, можно его копировать через memcpy и т.д.
Арифметика в указателях может плохо сказаться на производительности, как и выделение и освобождение памяти в цикле... Croessmah объяснил приём индексирования, который я использовал, не нарушая утверждения о массиве указателей)

Цитата:
Сообщение от Haric_110 Посмотреть сообщение
strings = new char *[m];
*strings = new char[m * n];
Цитата:
Сообщение от Haric_110 Посмотреть сообщение
ind_2 ^= ind_2;
while (++ind_2 < m) strings[ind_2] = strings[ind_2 - 1] + n;

Цитата:
Сообщение от Haric_110 Посмотреть сообщение
delete[] *strings; // выбрасывает исключение после выхода из оператора delete
delete[] strings;
но не работает, к сожалению, а почему — не знаю...
Другие варианты я тоже пробовал — они тоже не работают. Там исключение на первой итерации цикла.

Последний раз редактировалось Haric_110; 14.10.2017 в 15:27.
Haric_110 вне форума Ответить с цитированием
Старый 14.10.2017, 15:21   #14
Haric_110
Форумчанин
 
Регистрация: 03.03.2013
Сообщений: 102
По умолчанию

У меня вопрос: кто-нибудь пробовал компилировать мой код? Хотя бы в своём исправленном варианте? vector я использовать отказываюсь, потому что не дорос я до него ещё, слишком сишный я пока, сикотно мне), но так я лучше представляю, что происходит с памятью...

Последний раз редактировалось Haric_110; 14.10.2017 в 15:30.
Haric_110 вне форума Ответить с цитированием
Старый 14.10.2017, 15:33   #15
Haric_110
Форумчанин
 
Регистрация: 03.03.2013
Сообщений: 102
По умолчанию

Цитата:
Сообщение от alexzk Посмотреть сообщение
Кстати да, где-то встречал, что это эффективно, только на интелах. На других процах умножать быстрее, в итоге - лучше позволить компилятору решить, какой ассемблер делать. Хотя, думаю, сдвиг он тоже заменить умножением, если нужно.
Несложно поставить "следственный эксперимент" и выяснить истину. У меня ноут на AMD. Я использую сборку без оптимизации (Debug в Visual Studio), так компилятор ничего не заменяет, вроде...

Последний раз редактировалось Haric_110; 14.10.2017 в 15:35.
Haric_110 вне форума Ответить с цитированием
Старый 14.10.2017, 16:07   #16
Croessmah
Вредный кошак
Участник клуба
 
Аватар для Croessmah
 
Регистрация: 14.10.2012
Сообщений: 1,159
По умолчанию

Цитата:
В этой части кода ошибки нет
В этой чайти кода ошибка, приводящая к ub.
Как исправить я написал.
Цитата:
У меня вопрос: кто-нибудь пробовал компилировать мой код? Хотя бы в своём исправленном варианте?
У меня завелось там что-то после исправления.
Но я дальше особо не смотрел.
Цитата:
Я использую сборку без оптимизации (Debug в Visual Studio), так компилятор ничего не заменяет, вроде...
Зато кучу всего добавляет.
Дебаг сборка может работать на порядок медленнее.
Все тесты нужно выполнять только в релизе.
И большинство компиляторов выполнят
оптимизации намного лучше, чем программист.
Все Ваши x ^= x в принципе, бесполезны.

Последний раз редактировалось Croessmah; 14.10.2017 в 16:37.
Croessmah вне форума Ответить с цитированием
Старый 14.10.2017, 18:06   #17
Haric_110
Форумчанин
 
Регистрация: 03.03.2013
Сообщений: 102
По умолчанию

Croessmah,
Цитата:
Сообщение от Croessmah Посмотреть сообщение
Все Ваши x ^= x в принципе, бесполезны.
Считайте это просто стилем, как и отказ от for(,,)

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

Цитата:
Сообщение от Croessmah Посмотреть сообщение
Дебаг сборка может работать на порядок медленнее.
Зато она честно выполнит все операции кода (при отключенной оптимизации). Я думаю отдельную тему с тестом создать для разрешения спора, туда скрины настроек приложу, там это можно будет обсудить... а здесь касательно освобождения памяти, о том, что я написал...

Цитата:
Сообщение от Haric_110 Посмотреть сообщение
Код:
while (ind_2 < n) i[ind_2] = ind_2++;
Эту конструкцию я использую не в первый раз. выполняется она следующим образом:
1. проверяется условие цикла;
если истина, то:
a. выполняется действие в цикле (присваивание i[ind] значения ind);
b. выполняется инкрементирование после действия;
c. снова 1;
если ложь, то выход из цикла.

То есть, ровно так, как Вы написали.
Массив заполняется значениями от 0 до n-1, значение ind_2 после выхода из цикла равно n.
Пошаговая трассировка это подтверждает.

Последний раз редактировалось Haric_110; 14.10.2017 в 18:19.
Haric_110 вне форума Ответить с цитированием
Старый 14.10.2017, 18:27   #18
Croessmah
Вредный кошак
Участник клуба
 
Аватар для Croessmah
 
Регистрация: 14.10.2012
Сообщений: 1,159
По умолчанию

Цитата:
Сообщение от Haric_110 Посмотреть сообщение
но я не смогу ничего проверить, выполнив такую сборку.
С чего бы?
Что Вы там собрались вообще проверять?
Это именно то, что Вы получите в результате.
Цитата:
Сообщение от Haric_110 Посмотреть сообщение
Зато она честно выполнит все операции кода (при отключенной оптимизации).
А еще кучу всего лишнего.
А если в дебаге будет всё хорошо, а в релизе потом упадет,
то виновата, конечно же, сборка, а не автор кода.

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

Цитата:
Сообщение от Haric_110 Посмотреть сообщение
Эту конструкцию я использую не в первый раз. выполняется она следующим образом:
1. проверяется условие цикла;
если истина, то:
a. выполняется действие в цикле;
b. выполняется инкрементирование после действия;
c. снова 1;
если ложь, то выход из цикла.
Не обязательно так.

Цитата:
Сообщение от Haric_110 Посмотреть сообщение
Пошаговая трассировка это подтверждает.
Берем код с той же ошибкой:
Код:
#include <iostream>

int main()
{
    const int n = 3;
    int arr[n] = {555, 555, 555};
    int i = 0;
    while (i < n) {
        arr[i] = i++;
    }
    for(auto &e: arr) {
        std::cout << e << ", ";
    }
}
Смотрим на одном компиляторе (gcc): http://rextester.com/IAKLQC88748
Цитата:
555, 0, 1,
Смотрим на другом (CL): http://rextester.com/MSRRVL5172
Цитата:
0, 1, 2,
Оба поведения законны и ничего не нарушают в части языка,
но при выполнении будут проблемы,
мы же выходим за пределы массива.

Последний раз редактировалось Croessmah; 14.10.2017 в 18:58. Причина: вроде исправился )))
Croessmah вне форума Ответить с цитированием
Старый 14.10.2017, 18:33   #19
Haric_110
Форумчанин
 
Регистрация: 03.03.2013
Сообщений: 102
По умолчанию

Хорошо, я переписал код без лишних выпендрёжей:
Код:
#include <fstream>
#include <digital_counting_sort.h>
#include <iostream>

int main() {
	std::ifstream input;
	unsigned int n, m, k, *i, test_num = 0;
	char **strings;
	while (true) {
		std::cout << "test_" << ++test_num << " generation...";
		random_test_generator();												// создаёт файл с тестовыми данными

		input.open("input.txt");
		input >> n >> m >> k;

		std::cout << '\n'
			<< "nst = " << n << ", ncl = " << m << ", k = " << k << '\n'
			<< "status... ";

		i = new unsigned int[n];

		strings = new char *[m];
		*strings = new char[m * n];

		for (int ind = 0; ind < n; ++ind) i[ind] = ind;

		for (int ind = 1; ind < m; ++ind) strings[ind] = strings[ind - 1] + n;

		for (int ind_1 = 0; ind_1 < m; ++ind_1) {
			input >> strings[ind_1];
			for (int ind_2 = 0; ind_2 < n; ++ind_2) strings[ind_1][ind_2] -= 'a';
		}
		input.close();

		//digital_sort(strings, n, m, k, i);

		delete[] i;
		delete[] *strings;
		delete[] strings;

		std::cout << "done\n";
	}
	return 0;
}
Проблема та же

Последний раз редактировалось Haric_110; 14.10.2017 в 18:36.
Haric_110 вне форума Ответить с цитированием
Старый 14.10.2017, 18:35   #20
Croessmah
Вредный кошак
Участник клуба
 
Аватар для Croessmah
 
Регистрация: 14.10.2012
Сообщений: 1,159
По умолчанию

Цитата:
Сообщение от Haric_110 Посмотреть сообщение
Хорошо, я переписал код без лишних выпендрёжей:
Уберите вызов digital_sort, если проблема ушла, значит источник найден.
Если проблема не ушла, исключайте что-то еще, например, ввод данных.
Croessmah вне форума Ответить с цитированием
Ответ


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

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Утечка памяти [Освобождение памяти массива] denis76560 Общие вопросы Delphi 4 27.11.2016 18:20
Объявление динамического двумерного массива kineziz Общие вопросы C/C++ 4 27.05.2012 15:40
Освобождение памяти под динамический массив tsar_ Общие вопросы Delphi 7 24.12.2011 00:37
Матрица из двумерного динамического массива. Abrokadawr Фриланс 5 03.11.2011 22:28
Освобождение динамического массива? VintProg Общие вопросы Delphi 15 28.08.2009 10:41