Мой первый подход к этой проблеме был похож на тот, который был отправлен @Jeeped:
Используя MicroTimer Я вычислил среднее время, затраченное каждой частью алгоритма. Часть 3. заняла 90% -93% от общего времени выполнения для больших входных данных.
Ниже я попытался улучшить скорость записи данных на рабочий лист. Я определил константу iMinRSize=17
. После того, как возможно заполнить более iMinRSize
последовательные строки с тем же значением, код прекратит подавать массив и будет записываться непосредственно в диапазон рабочих листов.
Sub CrossJoin(rSrc As Range, rTrg As Range)
Dim vSrc() As Variant, vTrgPart() As Variant
Dim iLengths() As Long
Dim iCCnt As Integer, iRTrgCnt As Long, iRSrcCnt As Long
Dim i As Integer, j As Long, k As Long, l As Long
Dim iStep As Long
Const iMinRSize As Long = 17
Dim iArrLastC As Integer
On Error GoTo CleanUp
Application.ScreenUpdating = False
Application.EnableEvents = False
vSrc = rSrc.Value2
iCCnt = UBound(vSrc, 2)
iRSrcCnt = UBound(vSrc, 1)
iRTrgCnt = 1
iArrLastC = 1
ReDim iLengths(1 To iCCnt)
For i = 1 To iCCnt
j = iRSrcCnt
While (j > 0) And IsEmpty(vSrc(j, i))
j = j - 1
Wend
iLengths(i) = j
iRTrgCnt = iRTrgCnt * iLengths(i)
If (iRTrgCnt < iMinRSize) And (iArrLastC < iCCnt) Then iArrLastC = iArrLastC + 1
Next i
If (iRTrgCnt > 0) And (rTrg.row + iRTrgCnt - 1 <= rTrg.Parent.Rows.Count) Then
ReDim vTrgPart(1 To iRTrgCnt, 1 To iArrLastC)
iStep = 1
For i = 1 To iArrLastC
k = 0
For j = 1 To iRTrgCnt Step iStep
k = k + 1
If k > iLengths(i) Then k = 1
For l = j To j + iStep - 1
vTrgPart(l, i) = vSrc(k, i)
Next l
Next j
iStep = iStep * iLengths(i)
Next i
rTrg.Resize(iRTrgCnt, iArrLastC) = vTrgPart
For i = iArrLastC + 1 To iCCnt
k = 0
For j = 1 To iRTrgCnt Step iStep
k = k + 1
If k > iLengths(i) Then k = 1
rTrg.Resize(iStep).Offset(j - 1, i - 1).Value2 = vSrc(k, i)
Next j
iStep = iStep * iLengths(i)
Next i
End If
CleanUp:
Application.ScreenUpdating = True
Application.EnableEvents = False
End Sub
Sub test()
CrossJoin Range("a2:f10"), Range("k2")
End Sub
Если мы установим iMinRSize
в Rows.Count
, все данные записываются в массив. Ниже приведены мои тестовые результаты:
Код работает лучше всего, если первые столбцы с наибольшим количеством строк на первом месте, но это не будет большая проблема для изменения кода для ранжирования столбцов и обработки в правильном порядке.
(Примечание. Полный ответ должен содержать комментарий @ thokra, который означает, что main.cpp
является именем файла, а внешний вид точки входа в программу в файле с этим именем является только условным. довольно хорошо придерживался соглашения в Qt-программах и C ++ вообще, чтобы попытаться поместить точку входа в файл с таким именем.)
Одной категорией будет регистрация глобальных перехватов и настроек , Подумайте о таких вещах, как qInstallMessageHandler или QTextCodec :: setCodecForCStrings .
Инициализация любых библиотек non-Qt , которые ваше приложение хочет воспринимать как нечто само собой разумеющееся, будет другой областью.
Если ваша программа имеет объект главного окна, который только создается и уничтожается один раз, может показаться одинаково подходящим поставить код «запустить один раз» в его конструктор / деструктор. Но спросите себя, что это такое о вашем приложении, которое позволяет ему иметь только одно главное окно. Почему бы ему не иметь два в одном процессе? Даже если это не является частью сегодняшнего требования, оно может предложить архитектурную границу.
В личном опыте я упомянул, что если вы попытаетесь сделать класс, полученный из QApplication, а затем поместите свой глобальный запуск -код в конструкторе и деструкторе этого производного класса, что сложнее, чем кажется (особенно если вы создаете потоки и делаете виджеты в этом конструкторе) . Поэтому я не думаю, что в большинстве сценариев вы должны получить от QApplication. Я застрял в этом, потому что я создавал приложение framework ... но избегайте этого, и ваш код запуска выполняется в main.cpp.
"1. Является ли единственная цель main.cpp запуска приложения?"
blockquote>Как из c ++ [определение стандартов] 1 в первом разделе говорится:
3.6 Начало и окончание [basic.start] 3.6.1 Основная функция [basic.start.main] 1 Программа должна содержать глобальную функцию main, которая является назначенным началом программы. Реализация определяется, требуется ли программа в автономной среде для определения основной функции. [Примечание: В автономной среде запуск и завершение определяются реализацией; startup содержит выполнение конструкторов для объектов области пространства имен со статической продолжительностью хранения; завершение содержит выполнение деструкторов для объектов со статической продолжительностью хранения. -end note]
blockquote>Приложение qt все еще использует C ++, таким образом это ограничение должен быть удовлетворен для любого исполняемого приложения. Предположительно: Да, единственная цель
main()
- запустить приложение.
MainForm
иmain()
на самом деле не сильно связаны друг с другом, кроме вашей конфигурации будет генерироватьmain()
, создавая экземпляр и вызывая его. Вы также можете иметь проекты Qt, которые вообще не имеют экземпляраMainForm
(например, просто приложение командной строки).