| 
			| 
					
						| Ivan355 
								Новенький    Offline | 
								|  | «  : 06-04-2017 11:36 »  |  | 
 
 Всем доброго времени суток! Нужна ваша подсказка! Возникла проблема с рекурсивным поиском файлов. Накидал я функцию, но при работе выводит бесконечный список одинаковых файлоы и деректорий. Пытался переделать, были тоже ошибки выводился не весь список, или вообще ничего. Помогите доделать функцию, чтобы она работала правильно! Делал на основе примеров из гугла. В строках way_1, 2 и 3 храню путь. Вход функции search_file( "C:\\", "*.*"). Спасибо за помощь!!! int search_file(string dir, string mask){
 const char white_list_1[] = "Programm Files";
 const char white_list_2[] = "Programm Files (x86)";
 const char white_list_3[] = "Windows";
 string way_1 = dir;
 string way_2 = dir;
 string way_3 = way_2;
 way_1 = way_1 + mask;
 HANDLE hand;
 WIN32_FIND_DATA data_file;
 hand = FindFirstFile((way_1).c_str(), &data_file);
 if (hand != INVALID_HANDLE_VALUE)
 {
 do
 {
 if (lstrcmpA(data_file.cFileName, ".") == 0 || lstrcmpA(data_file.cFileName, "..") == 0)
 {
 continue;
 }
 if (lstrcmpA(data_file.cFileName, white_list_1) == 0 || lstrcmpA(data_file.cFileName, white_list_2) == 0 || lstrcmp(data_file.cFileName, white_list_3) == 0)
 {
 continue;
 }
 if (data_file.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM)
 {
 continue;
 }
 if (data_file.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
 {
 way_1 = dir + data_file.cFileName + '\\';
 cout << "dir -" << way_1 << endl;
 search_file(way_1, mask);
 }
 else
 {
 way_3 = way_3 + data_file.cFileName;
 cout << "file-" << way_3 << endl;
 }
 
 } while (FindNextFile(hand, &data_file));
 FindClose(hand);
 }
 return (1);
 }
 |  
						| 
								|  |  
								|  |  Записан | 
 |  |  | 
	| 
			| 
					
						| Aether | 
								|  | « Ответ #1 : 06-04-2017 13:03 »  |  | 
 
 Можно увидеть весь код программы? И, опечатка? int search_file(string dir, string mask){
 ...
 if (lstrcmpA(data_file.cFileName, white_list_1) == 0 || \
 lstrcmpA(data_file.cFileName, white_list_2) == 0 || \
 lstrcmp(data_file.cFileName, white_list_3) == 0)
 ...
 }
Везде lstrcmpA, кроме lstrcmp. |  
						| 
								|  |  
								|  |  Записан | 
 |  |  | 
	| 
			| 
					
						| Ivan355 
								Новенький    Offline | 
								|  | « Ответ #2 : 06-04-2017 14:05 »  |  | 
 
 Добрый день. Эта функция пока всё что у меня есть. В планах было после получения списка, что то делать с файлом, например нужный считывать или копировать. Я написал эту функцию и решил протестировать, в результате она не работает. Так и сижу на ней, пытаюсь понять что не так. Вродь нарыл, что нужно к пути добавить найденную папку и вызвать функцию снова, вродь так и делаю, а толку ноль. Да там ошибка, я забыл А в конце дописать...  |  
						| 
								|  |  
								|  |  Записан | 
 |  |  | 
	| 
			| 
					
						| Aether | 
								|  | « Ответ #3 : 06-04-2017 14:36 »  |  | 
 
 Общие соображения таковы: Когда Вы вызываете FindFirstFile, то он возвращает некий указатель, который в дальнейшем используется FindNextFile. Хранится hand, как переменная внутри функции, поэтому, когда происходит вложенный вызов это значение возможно изменится, и после возврата будет ссылаться на ветвь поиска, которая завершилась. Стало быть, хранить эту переменную нужно принудительно в стеке текущего вызова функции. Как это сделать лучше стоит поинтересоваться у более опытных участников. Чтобы разобраться попробуйте создать тестовое дерево директорий для поиска без файлов: С:\FIND_TEST\     С:\FIND_TEST\1     С:\FIND_TEST\2         С:\FIND_TEST\2\21         С:\FIND_TEST\2\22     С:\FIND_TEST\3 Далее, привести на форуме весь код, и вывод консоли. Для теста лучше упростить: int search_file(string dir, string mask)Добавлено через 6 часов, 52 минуты и 40 секунд:{
 string way = dir + mask;
 
 WIN32_FIND_DATA data_file;
 
 HANDLE hand = FindFirstFile((way).c_str(), &data_file);
 
 if (hand != INVALID_HANDLE_VALUE) {
 
 do {
 
 if (data_file.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
 
 way = dir + data_file.cFileName + '\\';
 cout << way << endl;
 search_file(way, mask);
 }
 
 } while (FindNextFile(hand, &data_file));
 
 FindClose(hand);
 }
 return (1);
 }
 Немного попрактиковался, конечно, далеко от идеала, и на С: #include <stdio.h>#include <malloc.h>
 #include <windows.h>
 
 char* stradd(char* first, char* second) {
 
 unsigned int size = strlen(first) + strlen(second) + 1;
 char* total = malloc(size);
 
 if (!total) return 0;
 
 char* dst = total;
 char* src = first;
 
 for (unsigned int i = 0; i < strlen(first); i++) {*dst++ = *src++;}
 
 src = second;
 
 for (unsigned int i = 0; i < strlen(second); i++) {*dst++ = *src++;}
 
 *dst = (char)0;
 
 return total;
 }
 
 void my_search_tree(char* dir, char* mask, int depth) {
 
 WIN32_FIND_DATA d;
 
 char* path = stradd(dir, mask);
 if (!path) return;
 
 /* printf("PATH: %s\n", path); */
 
 HANDLE h = FindFirstFile(path, &d);
 
 if (!h) return;
 
 do {
 
 if (d.cFileName[0] != '.') {
 
 if (d.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
 
 for (unsigned int j = 0; j < depth; j++) printf(" ");
 
 printf("FOUND: %s\n", d.cFileName);
 
 char* service = "\\";
 char* new_path_1 = stradd(dir, d.cFileName);
 
 if (!new_path_1) return;
 
 char* new_path_2 = stradd(new_path_1, service);
 
 if (!new_path_2) return;
 
 my_search_tree(new_path_2, mask, depth + 1);
 
 free(new_path_2);
 free(new_path_1);
 }
 }
 
 } while(FindNextFile(h, &d));
 
 free(path);
 }
 
 int main(int argc, char* argv) {
 
 my_search_tree("C:\\TDM64\\", "*.*", 0);
 
 return 0;
 }
 Результат: FOUND: binFOUND: gdb32
 FOUND: bin
 FOUND: DLLs
 FOUND: lib
 FOUND: bsddb
 FOUND: compiler
 FOUND: ctypes
 FOUND: macholib
 FOUND: curses
 FOUND: distutils
 FOUND: command
 FOUND: email
 FOUND: mime
 FOUND: encodings
 FOUND: ensurepip
 FOUND: _bundled
 FOUND: hotshot
 FOUND: idlelib
 FOUND: idle_test
 FOUND: importlib
 FOUND: json
 FOUND: lib-tk
 FOUND: test
 FOUND: test_tkinter
 FOUND: test_ttk
 FOUND: lib2to3
 FOUND: fixes
 FOUND: pgen2
 FOUND: tests
 FOUND: data
 FOUND: fixers
 FOUND: myfixes
 FOUND: logging
 FOUND: msilib
 FOUND: multiprocessing
 FOUND: dummy
 FOUND: pydoc_data
 FOUND: site-packages
 FOUND: sqlite3
 FOUND: test
 FOUND: audiodata
 FOUND: capath
 FOUND: cjkencodings
 FOUND: crashers
 FOUND: decimaltestdata
 FOUND: imghdrdata
 FOUND: leakers
 FOUND: subprocessdata
 FOUND: tracedmodules
 FOUND: xmltestdata
 FOUND: unittest
 FOUND: wsgiref
 FOUND: xml
 FOUND: dom
 FOUND: etree
 FOUND: parsers
 FOUND: sax
 FOUND: share
 FOUND: gdb
 FOUND: python
 FOUND: gdb
 FOUND: command
 FOUND: function
 FOUND: printer
 FOUND: syscalls
 FOUND: system-gdbinit
 FOUND: gdb64
 FOUND: bin
 FOUND: DLLs
 FOUND: lib
 FOUND: bsddb
 FOUND: compiler
 FOUND: ctypes
 FOUND: macholib
 FOUND: curses
 FOUND: distutils
 FOUND: command
 FOUND: email
 FOUND: mime
 FOUND: encodings
 FOUND: ensurepip
 FOUND: _bundled
 FOUND: hotshot
 FOUND: idlelib
 FOUND: idle_test
 FOUND: importlib
 FOUND: json
 FOUND: lib-tk
 FOUND: test
 FOUND: test_tkinter
 FOUND: test_ttk
 FOUND: lib2to3
 FOUND: fixes
 FOUND: pgen2
 FOUND: tests
 FOUND: data
 FOUND: fixers
 FOUND: myfixes
 FOUND: logging
 FOUND: msilib
 FOUND: multiprocessing
 FOUND: dummy
 FOUND: pydoc_data
 FOUND: site-packages
 FOUND: sqlite3
 FOUND: test
 FOUND: audiodata
 FOUND: capath
 FOUND: cjkencodings
 FOUND: crashers
 FOUND: decimaltestdata
 FOUND: imghdrdata
 FOUND: leakers
 FOUND: subprocessdata
 FOUND: tracedmodules
 FOUND: xmltestdata
 FOUND: unittest
 FOUND: wsgiref
 FOUND: xml
 FOUND: dom
 FOUND: etree
 FOUND: parsers
 FOUND: sax
 FOUND: share
 FOUND: gdb
 FOUND: python
 FOUND: gdb
 FOUND: command
 FOUND: function
 FOUND: printer
 FOUND: syscalls
 FOUND: system-gdbinit
 FOUND: include
 FOUND: lib
 FOUND: gcc
 FOUND: x86_64-w64-mingw32
 FOUND: 5.1.0
 FOUND: 32
 FOUND: adainclude
 FOUND: adalib
 FOUND: finclude
 FOUND: adainclude
 FOUND: adalib
 FOUND: finclude
 FOUND: include
 FOUND: c++
 FOUND: backward
 FOUND: bits
 FOUND: debug
 FOUND: decimal
 FOUND: experimental
 FOUND: ext
 FOUND: pb_ds
 FOUND: detail
 FOUND: binary_heap_
 FOUND: binomial_heap_
 FOUND: binomial_heap_base_
 FOUND: bin_search_tree_
 FOUND: branch_policy
 FOUND: cc_hash_table_map_
 FOUND: eq_fn
 FOUND: gp_hash_table_map_
 FOUND: hash_fn
 FOUND: left_child_next_sibling_heap_
 FOUND: list_update_map_
 FOUND: list_update_policy
 FOUND: ov_tree_map_
 FOUND: pairing_heap_
 FOUND: pat_trie_
 FOUND: rb_tree_map_
 FOUND: rc_binomial_heap_
 FOUND: resize_policy
 FOUND: splay_tree_
 FOUND: thin_heap_
 FOUND: tree_policy
 FOUND: trie_policy
 FOUND: unordered_iterator
 FOUND: parallel
 FOUND: profile
 FOUND: impl
 FOUND: tr1
 FOUND: tr2
 FOUND: x86_64-w64-mingw32
 FOUND: 32
 FOUND: bits
 FOUND: ext
 FOUND: bits
 FOUND: ext
 FOUND: objc
 FOUND: ssp
 FOUND: include-fixed
 FOUND: install-tools
 FOUND: include
 FOUND: plugin
 FOUND: libexec
 FOUND: gcc
 FOUND: x86_64-w64-mingw32
 FOUND: 5.1.0
 FOUND: install-tools
 FOUND: share
 FOUND: doc
 FOUND: make
 FOUND: 3.82.90
 FOUND: MinGW
 FOUND: gcc-5.1.0
 FOUND: python
 FOUND: libstdcxx
 FOUND: v6
 FOUND: info
 FOUND: man
 FOUND: man1
 FOUND: man5
 FOUND: man7
 FOUND: x86_64-w64-mingw32
 FOUND: bin
 FOUND: include
 FOUND: ddk
 FOUND: gdiplus
 FOUND: GL
 FOUND: psdk_inc
 FOUND: sdks
 FOUND: sec_api
 FOUND: sys
 FOUND: sys
 FOUND: lib
 FOUND: ldscripts
 FOUND: lib32
 FOUND: __installer
 FOUND: downloaded
 
 |  
						| 
								|  |  
								| « Последнее редактирование: 06-04-2017 21:29 от Aether » |  Записан | 
 |  |  | 
	| 
			| 
					
						| Aether | 
								|  | « Ответ #4 : 06-04-2017 21:34 »  |  | 
 
 Кстати, что-то у меня запало, что перед переменной нужно писать stack при рекурсии, а по умолчанию компилятор и так, оказывается, в стеке создаёт экземпляры? Глянул в документацию, а TCC имеет только слова: register и static.   |  
						| 
								|  |  
								|  |  Записан | 
 |  |  | 
	| 
			| 
					
						| Алексей++ 
								глобальный и пушистыйГлобальный модератор    Offline 
								Сообщений: 13
								
								
								
								
								
							 | 
								|  | « Ответ #5 : 07-04-2017 04:58 »  |  | 
 
 Aether, я не склонен к оптимизации копеечных расходов, но вот это, мне кажется, может довольно заметно сказаться на скорости for (unsigned int i = 0; i < strlen(src); i++) {*dst++ = *src++;}
ведь будет для каждого байта вызываться strlen, а потом этот байт копироваться вот так, думаю, правильнее int len=strlen(src)+1;//+1 место под ztif(len && len<= (тут размер, выделенный под dst) )
 {
 memmove(dst,src,len);
 }
 
никакого stack тоже не помню и не встречал. Тут компилятор лучше разберётся. А вообще, любую рекурсию можно развернуть в цикл - будет менее читаемо, но точно удобнее в отладке и по ресурсамДобавлено через 53 секунды: а ещё лучше - использовать c++   |  
						| 
								|  |  
								| « Последнее редактирование: 07-04-2017 04:58 от Алексей1153 » |  Записан | 
 
 |  |  | 
	| 
			| 
					
						| Dale | 
								|  | « Ответ #6 :  07-04-2017 08:32 »   |  | 
 
 Немного попрактиковался, конечно, далеко от идеала, и на С:     ...for (unsigned int i = 0; i < strlen(first); i++) {*dst++ = *src++;}
 ...
Мне больше нравится минимализм в стиле Кернигана и Ритчи, если уж не хотите пользоваться стандартными библиотечными функциями копирования цепочек литер:     ...while (*dst++ = *src++);
 ...
 никакого stack тоже не помню и не встречал. Этот копролит на самом деле называется "спецификатор класса памяти auto " и явно используется чуть реже чем никогда, поскольку все локальные переменные функции и так к нему относятся по умолчанию. |  
						| 
								|  |  
								|  |  Записан | 
 
 Всего лишь неделя кодирования с последующей неделей отладки могут сэкономить целый час, потраченный на планирование программы. - Дж. Коплин.
 Ходить по воде и разрабатывать программное обеспечение по спецификациям очень просто, когда и то, и другое заморожено. - Edward V. Berard
 
 Любые проблемы в информатике решаются добавлением еще одного уровня косвенности – кроме, разумеется, проблемы переизбытка уровней косвенности. — Дэвид Уилер.
 |  |  | 
	| 
			| 
					
						| Aether | 
								|  | « Ответ #7 : 07-04-2017 09:26 »  |  | 
 
 а ещё лучше - использовать c++  В С++ у меня очевидность теряется, вот, например: way = dir + data_file.cFileName + '\\';cout << way << endl;
 "+" - это стало быть оператор+ класса string и = тоже. При приравнивании старый way должен освободится, а с "+" должно происходить последовательное суммирование, в результате будут промежуточные выделения памяти - кто освободит их? Мне больше нравится минимализм в стиле Кернигана и Ритчи, если уж не хотите пользоваться стандартными библиотечными функциями копирования цепочек литер:
 ... все локальные переменные функции и так к нему относятся по умолчанию.
 
 Минимализм - это очень хорошо. То есть, ситуация обратная, получается: если не нужно хранить в стеке, то пишем static? |  
						| 
								|  |  
								|  |  Записан | 
 |  |  | 
	| 
			| 
					
						| Dale | 
								|  | « Ответ #8 : 07-04-2017 09:35 »  |  | 
 
 если не нужно хранить в стеке, то пишем static?static  пишем в первую очередь для того, чтобы значения переменной сохранялись между вызовами. Переменные с классом register  тоже могут не попасть в стек, но у них своя специфика. |  
						| 
								|  |  
								|  |  Записан | 
 
 Всего лишь неделя кодирования с последующей неделей отладки могут сэкономить целый час, потраченный на планирование программы. - Дж. Коплин.
 Ходить по воде и разрабатывать программное обеспечение по спецификациям очень просто, когда и то, и другое заморожено. - Edward V. Berard
 
 Любые проблемы в информатике решаются добавлением еще одного уровня косвенности – кроме, разумеется, проблемы переизбытка уровней косвенности. — Дэвид Уилер.
 |  |  | 
	| 
			| 
					
						| Алексей++ 
								глобальный и пушистыйГлобальный модератор    Offline 
								Сообщений: 13
								
								
								
								
								
							 | 
								|  | « Ответ #9 : 07-04-2017 11:17 »  |  | 
 
 Aether, std::string и освободит. Используй спокойно |  
						| 
								|  |  
								|  |  Записан | 
 
 |  |  | 
	| 
			| 
					
						| Ivan355 
								Новенький    Offline | 
								|  | « Ответ #10 : 09-04-2017 08:53 »  |  | 
 
 Ура, победа!!! получилось работает! переделал вот так: int search_file(char *dir, char *mask){
 HANDLE hand = NULL;
 const char white_list_1[] = "Programm Files";
 const char white_list_2[] = "Programm Files (x86)";
 const char white_list_3[] = "Windows";
 char way_1[MAX_PATH] = { "\0" };
 char way_2[MAX_PATH] = { "\0" };
 char way_3[MAX_PATH] = { "\0" };
 lstrcatA(way_1, dir);
 lstrcatA(way_2, way_1);
 lstrcatA(way_1, mask);
 WIN32_FIND_DATA data_file;
 hand = FindFirstFile(way_1, &data_file);
 if (hand != INVALID_HANDLE_VALUE)
 {
 do
 {
 if (lstrcmpA(data_file.cFileName, ".") == 0 || lstrcmpA(data_file.cFileName, "..") == 0)
 {
 continue;
 }
 if (lstrcmpA(data_file.cFileName, white_list_1) == 0 || lstrcmpA(data_file.cFileName, white_list_2) == 0 || lstrcmp(data_file.cFileName, white_list_3) == 0)
 {
 continue;
 }
 if (data_file.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM)
 {
 continue;
 }
 way_1[0] = { '\0' };
 lstrcatA(way_1, way_2);
 lstrcatA(way_1, data_file.cFileName);
 if (data_file.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
 {
 lstrcatA(way_1, "\\");
 cout << "dir -" << way_1 << endl;
 search_file(way_1, mask);
 }
 else
 {
 way_3[0] = { '\0' };
 lstrcatA(way_3, way_2);
 lstrcat(way_3, data_file.cFileName);
 cout << "file-" << way_3 << endl;
 }
 
 } while (FindNextFile(hand, &data_file));
 FindClose(hand);
 }
 return (1);
 }
 помог отказ от string. Всем огромное спасибо за помощь    |  
						| 
								|  |  
								|  |  Записан | 
 |  |  | 
	| 
			| 
					
						| Aether | 
								|  | « Ответ #11 : 09-04-2017 10:38 »  |  | 
 
 Aether, std::string и освободит. Используй спокойно
 #include <iostream>#include <windows.h>
 
 using namespace std;
 
 
 void my_search_tree(string dir, string mask, unsigned int depth) {
 
 WIN32_FIND_DATA d;
 
 if (dir.empty() || mask.empty()) return;
 
 string path = dir + mask;
 
 if (path.empty()) return;
 
 HANDLE h = FindFirstFile(path.c_str(), &d);
 
 if (!h) return;
 
 do {
 
 if (d.cFileName[0] != '.') {
 
 if (d.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
 
 for (unsigned int j = 0; j < depth; j++) cout << "  ";
 
 cout << dir << d.cFileName << endl;
 string new_path = dir + d.cFileName + "\\";
 
 my_search_tree(new_path, mask, depth + 1);
 
 } else {
 
 for (unsigned int j = 0; j < depth; j++) cout << "  ";
 
 cout << "   " << d.cFileName << endl;
 }
 }
 } while(FindNextFile(h, &d));
 }
 
 
 int main(int argc, char* argv[]) {
 
 string path = "C:\\TDM64\\";
 cout << "START: " << path << endl;
 
 my_search_tree(path, "*.*", 0);
 
 return 0;
 }
 START: C:\TDM64\C:\TDM64\bin
 addr2line.exe
 ar.exe
 as.exe
 c++.exe
 c++filt.exe
 cpp.exe
 dlltool.exe
 dllwrap.exe
 elfedit.exe
 g++.exe
 gcc-ar.exe
 gcc-nm.exe
 gcc-ranlib.exe
 gcc.exe
 gcov-tool.exe
 gcov.exe
 gdb.exe
 gdb32.exe
 gdb64.exe
 gdbserver.exe
 gdbserver32.exe
 gdbserver64.exe
 gfortran.exe
 gnat.exe
 gnatbind.exe
 gnatchop.exe
 gnatclean.exe
 gnatdll.exe
 gnatfind.exe
 gnatkr.exe
 gnatlink.exe
 gnatls.exe
 gnatmake.exe
 gnatname.exe
 gnatprep.exe
 gnatxref.exe
 gprof.exe
 ld.bfd.exe
 ld.exe
 libatomic-1.dll
 libatomic_64-1.dll
 libcharset-1.dll
 libgcc_s_dw2-1.dll
 libgcc_s_seh_64-1.dll
 libgcc_s_sjlj-1.dll
 libgfortran-3.dll
 libgfortran_64-3.dll
 libgnarl-5.dll
 libgnat-5.dll
 libgomp-1.dll
 libgomp-plugin-host_nonshm-1.dll
 libgomp-plugin-host_nonshm_64-1.dll
 libgomp_64-1.dll
 libiconv-2.dll
 libintl-8.dll
 libobjc-4.dll
 libobjc_64-4.dll
 libquadmath-0.dll
 libquadmath_64-0.dll
 libssp-0.dll
 libssp_64-0.dll
 libstdc++-6.dll
 libstdc++_64-6.dll
 libvtv-0.dll
 libvtv_64-0.dll
 libvtv_stubs-0.dll
 libvtv_stubs_64-0.dll
 libwinpthread-1.dll
 libwinpthread_64-1.dll
 mingw32-make.exe
 nm.exe
 objcopy.exe
 objdump.exe
 ranlib.exe
 readelf.exe
 size.exe
 strings.exe
 strip.exe
 windmc.exe
 windres.exe
 x86_64-w64-mingw32-c++.exe
 x86_64-w64-mingw32-g++.exe
 x86_64-w64-mingw32-gcc-5.1.0.exe
 x86_64-w64-mingw32-gcc-ar.exe
 x86_64-w64-mingw32-gcc-nm.exe
 x86_64-w64-mingw32-gcc-ranlib.exe
 x86_64-w64-mingw32-gcc.exe
 x86_64-w64-mingw32-gfortran.exe
 COPYING-expat.txt
 COPYING.ISL.txt
 COPYING.LIB.txt
 COPYING.MinGW-w64-runtime.txt
 COPYING.MinGW-w64.txt
 COPYING.RUNTIME-gcc-tdm.txt
 COPYING.winpthreads.txt
 COPYING3-gcc-tdm.txt
 COPYING3-gdb-tdm.txt
 COPYING3.LIB-gcc-tdm.txt
 C:\TDM64\gdb32
 C:\TDM64\gdb32\bin
 C:\TDM64\gdb32\bin\DLLs
 bz2.pyd
 py.ico
 pyc.ico
 pyexpat.pyd
 select.pyd
 sqlite3.dll
 unicodedata.pyd
 winsound.pyd
 _bsddb.pyd
 _ctypes.pyd
 _ctypes_test.pyd
 _elementtree.pyd
 _hashlib.pyd
 _msi.pyd
 _multiprocessing.pyd
 _socket.pyd
 _sqlite3.pyd
 _ssl.pyd
 _testcapi.pyd
 gdb32.exe
 gdbinit
 gdbserver32.exe
 C:\TDM64\gdb32\bin\lib
 ...
 
 Вопрос: по выходу из функции std::string сам вызовет деструктор, чтобы освободить память? |  
						| 
								|  |  
								| « Последнее редактирование: 09-04-2017 10:43 от Aether » |  Записан | 
 |  |  | 
	| 
			| 
					
						| Алексей++ 
								глобальный и пушистыйГлобальный модератор    Offline 
								Сообщений: 13
								
								
								
								
								
							 | 
								|  | « Ответ #12 : 09-04-2017 19:48 »  |  | 
 
 Aether, а что именно ему помешает освободить? 
 Добавлено через 2 минуты и 35 секунд:
 Aether, можешь поставить эксперимент:  сохрани указатель path.c_str() и в отладчике посмотри, что произойдёт с памятью в момент выхода из функции
 |  
						| 
								|  |  
								| « Последнее редактирование: 09-04-2017 19:52 от Алексей++ » |  Записан | 
 
 |  |  | 
	| 
			| 
					
						| Aether | 
								|  | « Ответ #13 : 10-04-2017 09:37 »  |  | 
 
 Aether, а что именно ему помешает освободить? 
 Я пытаюсь понять суть происходящего. Например: void test(void) {
 string a = "123456";
 cout << a;
 
 }
 Как я понимаю: в стеке будет создан указатель на структуру класса "a", а также сама структура класса "а". Где-то в памяти будет валяться массив char, оператор= вызовет функцию, которая сопоставит данные уже имеющейся структуры класса "а" с массивом char. При таком объявлении конструктор будет вызван при входе в функцию, а деструктор при выходе из неё? Надо будет похоже мне проработать эти нюансы. string test(void) {
 string a = "123456";
 cout << a;
 
 return string;
 }
 А здесь что произойдёт? Класс "a" передаст свои координаты приёмнику, а потом уничтожится? |  
						| 
								|  |  
								|  |  Записан | 
 |  |  | 
	| 
			| 
					
						| Aether | 
								|  | « Ответ #14 : 10-04-2017 16:21 »  |  | 
 
 Решил немного потестить: #include <iostream>#include <string>
 
 using namespace std;
 
 class info {
 public:
 info(string setup);
 ~info();
 private:
 string base;
 };
 
 info::info(string setup) {
 base = setup;
 cout << "  Build - " << base << endl;
 }
 
 info::~info() {
 cout << "  Destroy - " << base << endl;
 }
 
 void sub_function(unsigned int depth) {
 string s = to_string(depth);
 info sub(s);
 unsigned int a = depth - 1;
 
 if (a) sub_function(a);
 }
 
 int main(int argc, char* argv[]) {
 cout << "Start:" << endl;
 
 cout << "Prepare first object:" << endl;
 info first("First");
 
 cout << "Run sub_function:" << endl;
 sub_function(4);
 
 cout << "End." << endl;
 return 0;
 }
 Результат: Start:Prepare first object:
 Build - First
 Run sub_function:
 Build - 4
 Build - 3
 Build - 2
 Build - 1
 Destroy - 1
 Destroy - 2
 Destroy - 3
 Destroy - 4
 End.
 Destroy - First
 
 В общем, я мало сталкивался по серьёзному с плюсами, поэтому нюансы имеют место быть. |  
						| 
								|  |  
								|  |  Записан | 
 |  |  | 
	| 
			| 
					
						| Алексей++ 
								глобальный и пушистыйГлобальный модератор    Offline 
								Сообщений: 13
								
								
								
								
								
							 | 
								|  | « Ответ #15 : 10-04-2017 21:59 »  |  | 
 
 void test(){
 
 string a = "123456";
 cout << a;
 
 }
"123456" - это указатель на статический массив (где этот массив расположит компилятор - нам вообще неинтересно) на стеке создаётся экземпляр std::string с именем "a" , вызывается его конструктор std::string(char*), куда передаётся ссылка на массив по выходу из функции вызывается деструктор std::~string() чистится стек можешь посмотреть дизассемблер (я в дебаге смотрел, поэтому тут такая каша и всякие проверки) ;void test();{
 00696D10  push        ebp
 00696D11  mov         ebp,esp
 00696D13  sub         esp,2Ch
 00696D16  push        edi
 00696D17  lea         edi,[ebp-2Ch]
 00696D1A  mov         ecx,0Bh
 00696D1F  mov         eax,0CCCCCCCCh
 00696D24  rep stos    dword ptr es:[edi]
 00696D26  mov         eax,dword ptr [___security_cookie (0B9DD94h)]
 00696D2B  xor         eax,ebp
 00696D2D  mov         dword ptr [ebp-4],eax
 ;std::string a = "123456";
 00696D30  push        offset xxx::`vftable`+180h (0AA7A5Ch)
 00696D35  lea         ecx,[ebp-28h]
 00696D38  call        std::basic_string<char,std::char_traits<char>,std::allocator<char> >::basic_string<char,std::char_traits<char>,std::allocator<char> > (40EDE0h)
 ;}
 00696D3D  lea         ecx,[ebp-28h]
 00696D40  call        std::basic_string<char,std::char_traits<char>,std::allocator<char> >::~basic_string<char,std::char_traits<char>,std::allocator<char> > (40EE70h)
 00696D45  push        edx
 00696D46  mov         ecx,ebp
 00696D48  push        eax
 00696D49  lea         edx,[ (696D70h)]
 00696D4F  call        _RTC_CheckStackVars (8ED000h)
 00696D54  pop         eax
 00696D55  pop         edx
 00696D56  pop         edi
 00696D57  mov         ecx,dword ptr [ebp-4]
 00696D5A  xor         ecx,ebp
 00696D5C  call        __security_check_cookie (8ECFC0h)
 00696D61  add         esp,2Ch
 00696D64  cmp         ebp,esp
 00696D66  call        _RTC_CheckEsp (8ECFD0h)
 00696D6B  mov         esp,ebp
 00696D6D  pop         ebp
 00696D6E  ret
 string test(void) {
 string a = "123456";
 cout << a;
 
 return string;
 }
 - это не скомпилится. Если ты имел в виду "return a;" то всё будет так же, только в стеке останется копия - возвращаемый экземпляр std::string  std::string test2(){
 
 std::string a = "123456";
 
 return a;
 }
 
 ;std::string test2();{
 00696D90  push        ebp
 00696D91  mov         ebp,esp
 00696D93  push        0FFFFFFFFh
 00696D95  push        offset __ehhandler$?test2@@YA?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@XZ (9DC490h)
 00696D9A  mov         eax,dword ptr fs:[00000000h]
 00696DA0  push        eax
 00696DA1  sub         esp,30h
 00696DA4  push        edi
 00696DA5  lea         edi,[ebp-3Ch]
 00696DA8  mov         ecx,0Ch
 00696DAD  mov         eax,0CCCCCCCCh
 00696DB2  rep stos    dword ptr es:[edi]
 00696DB4  mov         eax,dword ptr [___security_cookie (0B9DD94h)]
 00696DB9  xor         eax,ebp
 00696DBB  mov         dword ptr [ebp-10h],eax
 00696DBE  push        eax
 00696DBF  lea         eax,[ebp-0Ch]
 00696DC2  mov         dword ptr fs:[00000000h],eax
 00696DC8  mov         dword ptr [ebp-3Ch],0
 
 ;std::string a = "123456";
 00696DCF  push        offset xxx::`vftable`+188h (0AA7A64h)
 00696DD4  lea         ecx,[ebp-34h]
 00696DD7  call        std::basic_string<char,std::char_traits<char>,std::allocator<char> >::basic_string<char,std::char_traits<char>,std::allocator<char> > (40EDE0h)
 00696DDC  mov         dword ptr [ebp-4],1
 
 ;return a;
 00696DE3  lea         eax,[ebp-34h]
 00696DE6  push        eax
 00696DE7  mov         ecx,dword ptr [ebp+8]
 00696DEA  call        std::basic_string<char,std::char_traits<char>,std::allocator<char> >::basic_string<char,std::char_traits<char>,std::allocator<char> > (411B50h)
 00696DEF  mov         ecx,dword ptr [ebp-3Ch]
 00696DF2  or          ecx,1
 00696DF5  mov         dword ptr [ebp-3Ch],ecx
 00696DF8  mov         byte ptr [ebp-4],0
 00696DFC  lea         ecx,[ebp-34h]
 00696DFF  call        std::basic_string<char,std::char_traits<char>,std::allocator<char> >::~basic_string<char,std::char_traits<char>,std::allocator<char> > (40EE70h)
 00696E04  mov         eax,dword ptr [ebp+8]
 ;}
 00696E07  push        edx
 00696E08  mov         ecx,ebp
 00696E0A  push        eax
 00696E0B  lea         edx,[ (696E3Ch)]
 00696E11  call        _RTC_CheckStackVars (8ED0E0h)
 00696E16  pop         eax
 00696E17  pop         edx
 00696E18  mov         ecx,dword ptr [ebp-0Ch]
 00696E1B  mov         dword ptr fs:[0],ecx
 00696E22  pop         ecx
 00696E23  pop         edi
 00696E24  mov         ecx,dword ptr [ebp-10h]
 00696E27  xor         ecx,ebp
 00696E29  call        __security_check_cookie (8ED0A0h)
 00696E2E  add         esp,3Ch
 00696E31  cmp         ebp,esp
 00696E33  call        _RTC_CheckEsp (8ED0B0h)
 00696E38  mov         esp,ebp
 00696E3A  pop         ebp
 00696E3B  ret
 |  
						| 
								|  |  
								|  |  Записан | 
 
 |  |  | 
	| 
			| 
					
						| Finch 
								СпокойныйАдминистратор    Offline 
								Пол:    
								Пролетал мимо
								
								
								
								
								
							 | 
								|  | « Ответ #16 : 11-04-2017 04:22 »  |  | 
 
 Есть довольно мошная утилитка для тестирования течи памяти в том числе. Называется valgrind. Вот лог тестирование им твоего примера. $ g++ auth.cpp -o auth -g -Wall$ valgrind ./auth
 ==6917== Memcheck, a memory error detector
 ==6917== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
 ==6917== Using Valgrind-3.12.0 and LibVEX; rerun with -h for copyright info
 ==6917== Command: ./auth
 ==6917==
 Start:
 Prepare first object:
 Build - First
 Run sub_function:
 Build - 4
 Build - 3
 Build - 2
 Build - 1
 Destroy - 1
 Destroy - 2
 Destroy - 3
 Destroy - 4
 End.
 Destroy - First
 ==6917==
 ==6917== HEAP SUMMARY:
 ==6917==     in use at exit: 0 bytes in 0 blocks
 ==6917==   total heap usage: 2 allocs, 2 frees, 73,728 bytes allocated
 ==6917==
 ==6917== All heap blocks were freed -- no leaks are possible
 ==6917==
 ==6917== For counts of detected and suppressed errors, rerun with: -v
 ==6917== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
 
 |  
						| 
								|  |  
								| « Последнее редактирование: 11-04-2017 04:24 от Finch » |  Записан | 
 
 Не будите спашяго дракона.              Джаффар (Коша) |  |  | 
	| 
			| 
					
						| Aether | 
								|  | « Ответ #17 : 11-04-2017 17:09 »  |  | 
 
 Тоже немного поэкспериментировал, теперь пытаюсь понять что тут и где: #include <iostream>
 using namespace std;
 
 class test {
 public:
 test(unsigned int setup);
 ~test();
 void inc();
 void print();
 private:
 unsigned int value;
 };
 
 test::test(unsigned int setup) {
 value = setup;
 cout << "  Build" << endl;
 }
 
 test::~test() {
 cout << "  Destroy" << endl;
 }
 
 void test::inc() {
 value++;
 }
 
 void test::print() {
 cout << value << endl;
 }
 
 test create(test in) {
 return in;
 }
 
 int main(int argc, char* argv[]) {
 cout << "Start:" << endl;
 
 cout << "Step 1: prepare first object" << endl;
 unsigned int a = 5;
 test obj_1(a);
 obj_1.print();
 
 cout << "Step 2: change \"a\" value" << endl;
 a = 6;
 obj_1.print();
 
 cout << "Step 3: change private value" << endl;
 obj_1.inc();
 obj_1.print();
 
 cout << "Step 4: prepare second object" << endl;
 test obj_2 = create(obj_1);
 obj_1.print();
 obj_2.print();
 
 cout << "Step 5: inc first object" << endl;
 obj_1.inc();
 obj_1.print();
 obj_2.print();
 
 cout << "End." << endl;
 return 0;
 }
         .file   "test_3.cpp".intel_syntax noprefix
 .section .rdata,"dr"
 __ZStL19piecewise_construct:
 .space 1
 .lcomm __ZStL8__ioinit,1,1
 LC0:
 .ascii "  Build\0"
 .text
 .align 2
 .globl  __ZN4testC2Ej
 .def    __ZN4testC2Ej;  .scl    2;      .type   32;     .endef
 __ZN4testC2Ej:
 push    ebp
 mov     ebp, esp
 sub     esp, 40
 mov     DWORD PTR [ebp-12], ecx
 mov     eax, DWORD PTR [ebp-12]
 mov     edx, DWORD PTR [ebp+8]
 mov     DWORD PTR [eax], edx
 mov     DWORD PTR [esp+4], OFFSET FLAT:LC0
 mov     DWORD PTR [esp], OFFSET FLAT:__ZSt4cout
 call    __ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc
 mov     DWORD PTR [esp], OFFSET FLAT:__ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_
 mov     ecx, eax
 call    __ZNSolsEPFRSoS_E
 sub     esp, 4
 nop
 leave
 ret     4
 .globl  __ZN4testC1Ej
 .def    __ZN4testC1Ej;  .scl    2;      .type   32;     .endef
 .set    __ZN4testC1Ej,__ZN4testC2Ej
 .section .rdata,"dr"
 LC1:
 .ascii "  Destroy\0"
 .def    ___gxx_personality_sj0; .scl    2;      .type   32;     .endef
 .def    __Unwind_SjLj_Register; .scl    2;      .type   32;     .endef
 .def    __Unwind_SjLj_Unregister;       .scl    2;      .type   32;     .endef
 .text
 .align 2
 .globl  __ZN4testD2Ev
 .def    __ZN4testD2Ev;  .scl    2;      .type   32;     .endef
 __ZN4testD2Ev:
 push    ebp
 mov     ebp, esp
 sub     esp, 88
 mov     DWORD PTR [ebp-12], ecx
 mov     DWORD PTR [ebp-40], OFFSET FLAT:___gxx_personality_sj0
 mov     DWORD PTR [ebp-36], OFFSET FLAT:LLSDA1413
 lea     eax, [ebp-64]
 mov     DWORD PTR [esp], eax
 call    __Unwind_SjLj_Register
 mov     DWORD PTR [esp+4], OFFSET FLAT:LC1
 mov     DWORD PTR [esp], OFFSET FLAT:__ZSt4cout
 mov     DWORD PTR [ebp-60], 0
 call    __ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc
 mov     DWORD PTR [esp], OFFSET FLAT:__ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_
 mov     ecx, eax
 call    __ZNSolsEPFRSoS_E
 sub     esp, 4
 nop
 lea     eax, [ebp-64]
 mov     DWORD PTR [esp], eax
 call    __Unwind_SjLj_Unregister
 leave
 ret
 .section        .gcc_except_table,"w"
 LLSDA1413:
 .byte   0xff
 .byte   0xff
 .byte   0x1
 .uleb128 LLSDACSE1413-LLSDACSB1413
 LLSDACSB1413:
 LLSDACSE1413:
 .text
 .globl  __ZN4testD1Ev
 .def    __ZN4testD1Ev;  .scl    2;      .type   32;     .endef
 .set    __ZN4testD1Ev,__ZN4testD2Ev
 .align 2
 .globl  __ZN4test3incEv
 .def    __ZN4test3incEv;        .scl    2;      .type   32;     .endef
 __ZN4test3incEv:
 push    ebp
 mov     ebp, esp
 sub     esp, 4
 mov     DWORD PTR [ebp-4], ecx
 mov     eax, DWORD PTR [ebp-4]
 mov     eax, DWORD PTR [eax]
 lea     edx, [eax+1]
 mov     eax, DWORD PTR [ebp-4]
 mov     DWORD PTR [eax], edx
 nop
 leave
 ret
 .align 2
 .globl  __ZN4test5printEv
 .def    __ZN4test5printEv;      .scl    2;      .type   32;     .endef
 __ZN4test5printEv:
 push    ebp
 mov     ebp, esp
 sub     esp, 40
 mov     DWORD PTR [ebp-12], ecx
 mov     eax, DWORD PTR [ebp-12]
 mov     eax, DWORD PTR [eax]
 mov     DWORD PTR [esp], eax
 mov     ecx, OFFSET FLAT:__ZSt4cout
 call    __ZNSolsEj
 sub     esp, 4
 mov     DWORD PTR [esp], OFFSET FLAT:__ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_
 mov     ecx, eax
 call    __ZNSolsEPFRSoS_E
 sub     esp, 4
 nop
 leave
 ret
 .globl  __Z6create4test
 .def    __Z6create4test;        .scl    2;      .type   32;     .endef
 __Z6create4test:
 push    ebp
 mov     ebp, esp
 mov     eax, DWORD PTR [ebp+8]
 mov     edx, DWORD PTR [ebp+12]
 mov     edx, DWORD PTR [edx]
 mov     DWORD PTR [eax], edx
 mov     eax, DWORD PTR [ebp+8]
 pop     ebp
 ret
 .def    ___main;        .scl    2;      .type   32;     .endef
 .section .rdata,"dr"
 LC2:
 .ascii "Start:\0"
 LC3:
 .ascii "Step 1: prepare first object\0"
 LC4:
 .ascii "Step 2: change \"a\" value\0"
 LC5:
 .ascii "Step 3: change private value\0"
 LC6:
 .ascii "Step 4: prepare second object\0"
 LC7:
 .ascii "Step 5: inc first object\0"
 LC8:
 .ascii "End.\0"
 .text
 .globl  _main
 .def    _main;  .scl    2;      .type   32;     .endef
 _main:
 lea     ecx, [esp+4]
 and     esp, -16
 push    DWORD PTR [ecx-4]
 push    ebp
 mov     ebp, esp
 push    edi
 push    esi
 push    ebx
 push    ecx
 sub     esp, 104
 mov     DWORD PTR [ebp-68], OFFSET FLAT:___gxx_personality_sj0
 mov     DWORD PTR [ebp-64], OFFSET FLAT:LLSDA1418
 lea     eax, [ebp-60]
 lea     ebx, [ebp-24]
 mov     DWORD PTR [eax], ebx
 mov     edx, OFFSET FLAT:L11
 mov     DWORD PTR [eax+4], edx
 mov     DWORD PTR [eax+8], esp
 lea     eax, [ebp-92]
 mov     DWORD PTR [esp], eax
 call    __Unwind_SjLj_Register
 call    ___main
 mov     DWORD PTR [esp+4], OFFSET FLAT:LC2
 mov     DWORD PTR [esp], OFFSET FLAT:__ZSt4cout
 mov     DWORD PTR [ebp-88], -1
 call    __ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc
 mov     DWORD PTR [esp], OFFSET FLAT:__ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_
 mov     ecx, eax
 call    __ZNSolsEPFRSoS_E
 sub     esp, 4
 mov     DWORD PTR [esp+4], OFFSET FLAT:LC3
 mov     DWORD PTR [esp], OFFSET FLAT:__ZSt4cout
 call    __ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc
 mov     DWORD PTR [esp], OFFSET FLAT:__ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_
 mov     ecx, eax
 call    __ZNSolsEPFRSoS_E
 sub     esp, 4
 mov     DWORD PTR [ebp-28], 5
 lea     eax, [ebp-36]
 mov     edx, DWORD PTR [ebp-28]
 mov     DWORD PTR [esp], edx
 mov     ecx, eax
 call    __ZN4testC1Ej
 sub     esp, 4
 lea     eax, [ebp-36]
 mov     DWORD PTR [ebp-88], 1
 mov     ecx, eax
 call    __ZN4test5printEv
 mov     DWORD PTR [esp+4], OFFSET FLAT:LC4
 mov     DWORD PTR [esp], OFFSET FLAT:__ZSt4cout
 call    __ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc
 mov     DWORD PTR [esp], OFFSET FLAT:__ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_
 mov     ecx, eax
 call    __ZNSolsEPFRSoS_E
 sub     esp, 4
 mov     DWORD PTR [ebp-28], 6
 lea     eax, [ebp-36]
 mov     ecx, eax
 call    __ZN4test5printEv
 mov     DWORD PTR [esp+4], OFFSET FLAT:LC5
 mov     DWORD PTR [esp], OFFSET FLAT:__ZSt4cout
 call    __ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc
 mov     DWORD PTR [esp], OFFSET FLAT:__ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_
 mov     ecx, eax
 call    __ZNSolsEPFRSoS_E
 sub     esp, 4
 lea     eax, [ebp-36]
 mov     ecx, eax
 call    __ZN4test3incEv
 lea     eax, [ebp-36]
 mov     ecx, eax
 call    __ZN4test5printEv
 mov     DWORD PTR [esp+4], OFFSET FLAT:LC6
 mov     DWORD PTR [esp], OFFSET FLAT:__ZSt4cout
 call    __ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc
 mov     DWORD PTR [esp], OFFSET FLAT:__ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_
 mov     ecx, eax
 call    __ZNSolsEPFRSoS_E
 sub     esp, 4
 mov     eax, DWORD PTR [ebp-36]
 mov     DWORD PTR [ebp-32], eax
 lea     eax, [ebp-40]
 lea     edx, [ebp-32]
 mov     DWORD PTR [esp+4], edx
 mov     DWORD PTR [esp], eax
 call    __Z6create4test
 lea     eax, [ebp-32]
 mov     ecx, eax
 call    __ZN4testD1Ev
 lea     eax, [ebp-36]
 mov     DWORD PTR [ebp-88], 2
 mov     ecx, eax
 call    __ZN4test5printEv
 lea     eax, [ebp-40]
 mov     ecx, eax
 call    __ZN4test5printEv
 mov     DWORD PTR [esp+4], OFFSET FLAT:LC7
 mov     DWORD PTR [esp], OFFSET FLAT:__ZSt4cout
 call    __ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc
 mov     DWORD PTR [esp], OFFSET FLAT:__ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_
 mov     ecx, eax
 call    __ZNSolsEPFRSoS_E
 sub     esp, 4
 lea     eax, [ebp-36]
 mov     ecx, eax
 call    __ZN4test3incEv
 lea     eax, [ebp-36]
 mov     ecx, eax
 call    __ZN4test5printEv
 lea     eax, [ebp-40]
 mov     ecx, eax
 call    __ZN4test5printEv
 mov     DWORD PTR [esp+4], OFFSET FLAT:LC8
 mov     DWORD PTR [esp], OFFSET FLAT:__ZSt4cout
 call    __ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc
 mov     DWORD PTR [esp], OFFSET FLAT:__ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_
 mov     ecx, eax
 call    __ZNSolsEPFRSoS_E
 sub     esp, 4
 mov     DWORD PTR [ebp-96], 0
 lea     eax, [ebp-40]
 mov     ecx, eax
 call    __ZN4testD1Ev
 lea     eax, [ebp-36]
 mov     ecx, eax
 call    __ZN4testD1Ev
 mov     eax, DWORD PTR [ebp-96]
 mov     DWORD PTR [ebp-96], eax
 jmp     L14
 L13:
 mov     DWORD PTR [ebp-96], edx
 lea     eax, [ebp-40]
 mov     ecx, eax
 call    __ZN4testD1Ev
 mov     eax, DWORD PTR [ebp-96]
 mov     DWORD PTR [ebp-96], eax
 jmp     L10
 L11:
 lea     ebp, [ebp+24]
 mov     edx, DWORD PTR [ebp-84]
 mov     eax, DWORD PTR [ebp-88]
 test    eax, eax
 je      L12
 sub     eax, 1
 test    eax, eax
 je      L13
 sub     eax, 1
 ud2
 L12:
 mov     DWORD PTR [ebp-96], edx
 L10:
 lea     eax, [ebp-36]
 mov     ecx, eax
 call    __ZN4testD1Ev
 mov     eax, DWORD PTR [ebp-96]
 mov     DWORD PTR [esp], eax
 mov     DWORD PTR [ebp-88], -1
 call    __Unwind_SjLj_Resume
 L14:
 lea     eax, [ebp-92]
 mov     DWORD PTR [esp], eax
 call    __Unwind_SjLj_Unregister
 mov     eax, DWORD PTR [ebp-96]
 lea     esp, [ebp-16]
 pop     ecx
 pop     ebx
 pop     esi
 pop     edi
 pop     ebp
 lea     esp, [ecx-4]
 ret
 .section        .gcc_except_table,"w"
 LLSDA1418:
 .byte   0xff
 .byte   0xff
 .byte   0x1
 .uleb128 LLSDACSE1418-LLSDACSB1418
 LLSDACSB1418:
 .uleb128 0
 .uleb128 0
 .uleb128 0x1
 .uleb128 0
 LLSDACSE1418:
 .text
 .def    ___tcf_0;       .scl    3;      .type   32;     .endef
 ___tcf_0:
 push    ebp
 mov     ebp, esp
 sub     esp, 8
 mov     ecx, OFFSET FLAT:__ZStL8__ioinit
 call    __ZNSt8ios_base4InitD1Ev
 leave
 ret
 .def    __Z41__static_initialization_and_destruction_0ii;       .scl    3;      .type   32;     .endef
 __Z41__static_initialization_and_destruction_0ii:
 push    ebp
 mov     ebp, esp
 sub     esp, 24
 cmp     DWORD PTR [ebp+8], 1
 jne     L18
 cmp     DWORD PTR [ebp+12], 65535
 jne     L18
 mov     ecx, OFFSET FLAT:__ZStL8__ioinit
 call    __ZNSt8ios_base4InitC1Ev
 mov     DWORD PTR [esp], OFFSET FLAT:___tcf_0
 call    _atexit
 L18:
 nop
 leave
 ret
 .def    __GLOBAL__sub_I__ZN4testC2Ej;   .scl    3;      .type   32;     .endef
 __GLOBAL__sub_I__ZN4testC2Ej:
 push    ebp
 mov     ebp, esp
 sub     esp, 24
 mov     DWORD PTR [esp+4], 65535
 mov     DWORD PTR [esp], 1
 call    __Z41__static_initialization_and_destruction_0ii
 leave
 ret
 .section        .ctors,"w"
 .align 4
 .long   __GLOBAL__sub_I__ZN4testC2Ej
 .ident  "GCC: (tdm64-1) 5.1.0"
 .def    __ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc;       .scl    2;      .type   32;     .endef
 .def    __ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_;    .scl    2;      .type   32;     .endef
 .def    __ZNSolsEPFRSoS_E;      .scl    2;      .type   32;     .endef
 .def    __ZNSolsEj;     .scl    2;      .type   32;     .endef
 .def    __Unwind_SjLj_Resume;   .scl    2;      .type   32;     .endef
 .def    __ZNSt8ios_base4InitD1Ev;       .scl    2;      .type   32;     .endef
 .def    __ZNSt8ios_base4InitC1Ev;       .scl    2;      .type   32;     .endef
 .def    _atexit;        .scl    2;      .type   32;     .endef
 Start:Step 1: prepare first object
 Build
 5
 Step 2: change "a" value
 5
 Step 3: change private value
 6
 Step 4: prepare second object
 Destroy
 6
 6
 Step 5: inc first object
 7
 6
 End.
 Destroy
 Destroy
 
 Получается, что приравнять классы - это не то же самое, что приравнять указатели на их структуры. Самое удивительное, что при копировании не вызывается конструктор. Как же быть, если в составе класса будет указатель на какой-то выделенный блок памяти? В клоне класса будет ссылка в никуда. Мне кажется, что это не совсем логично, тогда "=" должно быть определённым пользователем методом, таким, чтобы копирование структур происходило правильно. |  
						| 
								|  |  
								|  |  Записан | 
 |  |  | 
	| 
			| 
					
						| Finch 
								СпокойныйАдминистратор    Offline 
								Пол:    
								Пролетал мимо
								
								
								
								
								
							 | 
								|  | « Ответ #18 : 11-04-2017 18:50 »  |  | 
 
 Не совсем так. Вызывается конструктор копирования. Если он не определен в классе, то по умолчанию. Поэтому при динамических переменных, его нужно обязательно определять в классе. |  
						| 
								|  |  
								|  |  Записан | 
 
 Не будите спашяго дракона.              Джаффар (Коша) |  |  | 
	| 
			| 
					
						| Aether | 
								|  | « Ответ #19 : 11-04-2017 20:34 »  |  | 
 
 А как такой конструктор организовать в рамках моего примера? Он будет надстройкой КК по умолчанию? Или же придётся полностью реализовывать копирование, в том числе, статичных элементов класса?
 Впрочем, что-то стало яснее - это однозначно.)
 |  
						| 
								|  |  
								|  |  Записан | 
 |  |  | 
	| 
			| 
					
						| Aether | 
								|  | « Ответ #20 : 11-04-2017 20:55 »  |  | 
 
 Как-то так? test::test(const test& object) {value = object.value;
 cout << "  Copy" << endl;
 }
 Start:Step 1: prepare first object
 Build
 5
 Step 2: change "a" value
 5
 Step 3: change private value
 6
 Step 4: prepare second object
 Copy
 Copy
 Destroy
 6
 6
 Step 5: inc first object
 7
 6
 End.
 Destroy
 Destroy
 
 |  
						| 
								|  |  
								|  |  Записан | 
 |  |  | 
	| 
			| 
					
						| RXL | 
								|  | « Ответ #21 : 11-04-2017 21:11 »  |  | 
 
 Куда ты собрался копировать статические члены класса? Они, по сути, простые статические переменные с видимостью определяемой классом. Т.е. существуют в единственном количестве. |  
						| 
								|  |  
								|  |  Записан | 
 
 ... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С. |  |  | 
	| 
			| 
					
						| Finch 
								СпокойныйАдминистратор    Offline 
								Пол:    
								Пролетал мимо
								
								
								
								
								
							 | 
								|  | « Ответ #22 : 11-04-2017 21:28 »  |  | 
 
 Как-то так?
 Ага   |  
						| 
								|  |  
								|  |  Записан | 
 
 Не будите спашяго дракона.              Джаффар (Коша) |  |  | 
	| 
			| 
					
						| Aether | 
								|  | « Ответ #23 : 12-04-2017 11:00 »  |  | 
 
 Куда ты собрался копировать статические члены класса? Они, по сути, простые статические переменные с видимостью определяемой классом. Т.е. существуют в единственном количестве.
 Как куда? Из одного экземпляра в другой. Если в КК убрать: value = object.value; То в объекте приёмнике value станет произвольным числом, если же написать: value = 0; То после копирования значение сбросится на ноль, и неважно что там return возвращал. В общем, как я понял, при входе и выходе из функции, в том числе main создаётся стековый кадр на размер структуры класса, после чего, если не определён КК, происходит полное копирование данных класса источника в класс приёмник. Если же КК определён, то кадр содержит мусор, и его нужно заполнять всецело самому. А если есть динамические выделения, то управлять и ими. Сейчас думаю: чем передача по ссылке отличается от передачи по указателю? |  
						| 
								|  |  
								|  |  Записан | 
 |  |  | 
	| 
			| 
					
						| Алексей++ 
								глобальный и пушистыйГлобальный модератор    Offline 
								Сообщений: 13
								
								
								
								
								
							 | 
								|  | « Ответ #24 : 12-04-2017 15:02 »  |  | 
 
  Или же придётся полностью реализовывать копирование, в том числе, статичных элементов класса?Aether
 , RXL , немного не поняли друг друга , мне кажется не знаю, что именно Aether назвал "статичные переменные", но Рома точно подумал про статические, а тут не про них явно )) Сейчас думаю: чем передача по ссылке отличается от передачи по указателю? практически ничем |  
						| 
								|  |  
								|  |  Записан | 
 
 |  |  | 
	| 
			| 
					
						| Aether | 
								|  | « Ответ #25 : 12-04-2017 17:09 »  |  | 
 
 практически ничем
 А для чего тогда так сделали? |  
						| 
								|  |  
								|  |  Записан | 
 |  |  | 
	| 
			| 
					
						| RXL | 
								|  | « Ответ #26 : 12-04-2017 23:52 »  |  | 
 
 Семантика ссылки и указателя разная.Для доступа к членам для ссылки используется оператор ".". С указателем используются операторы "->" и "*".
 Указатель может быть нулевым, а ссылка нет.
 Как следствие, ссылка должна быть инициализирована при создании и не может быть присвоена. Указатель может быть как инициализирован, так и присвоен.
 
 |  
						| 
								|  |  
								| « Последнее редактирование: 12-04-2017 23:55 от RXL » |  Записан | 
 
 ... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С. |  |  | 
	| 
			| 
					
						| Алексей++ 
								глобальный и пушистыйГлобальный модератор    Offline 
								Сообщений: 13
								
								
								
								
								
							 | 
								|  | « Ответ #27 : 13-04-2017 04:43 »  |  | 
 
 Aether, ссылку изменить нельзя         int a=0;int& ref_a1=a;//первая ссылка на а
 int& ref_a2=ref_a1;//вторая ссылка на a
 
 int b=0;
 ref_a2=b;//изменить ссылку нельзя (здесь выполняется a=b)
 то есть, ссылка - это псевдоним уже существующей переменной указатель можно менять         int a=0;int* ptr_a1=&a;//ptr_a1 - указатель на a
 *ptr_a1=1;//здесь выполняется a=1
 
 int b=0;
 ptr_a1=&b;//теперь ptr_a1 - указатель на b
 *ptr_a1=2;//здесь выполняется b=2
 |  
						| 
								|  |  
								|  |  Записан | 
 
 |  |  | 
	| 
			| 
					
						| Aether | 
								|  | « Ответ #28 : 13-04-2017 10:38 »  |  | 
 
 Семантика ссылки и указателя разная.
 То есть, из-за того, что класс может быть и динамическим придумано такое упрощение? Aether, ссылку изменить нельзя
 Кстати, почему в шаблоне для КК нужно в качестве аргумента писать именно const? |  
						| 
								|  |  
								|  |  Записан | 
 |  |  | 
	| 
			| 
					
						| Алексей++ 
								глобальный и пушистыйГлобальный модератор    Offline 
								Сообщений: 13
								
								
								
								
								
							 | 
								|  | « Ответ #29 : 13-04-2017 16:44 »  |  | 
 
 Aether, я не знаю такое - "динамический класс"
 конструктор копирования имеет определённый прототип. Ну и это же копирование, так что источник не должен изменяться
 |  
						| 
								|  |  
								|  |  Записан | 
 
 |  |  | 
	|  |