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) {     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); } Добавлено через 6 часов, 52 минуты и 40 секунд:Немного попрактиковался, конечно, далеко от идеала, и на С: #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: bin FOUND: 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 место под zt if(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, я не знаю такое - "динамический класс"
  конструктор копирования имеет определённый прототип. Ну и это же копирование, так что источник не должен изменяться 
						 | 
					 
					
						
							
								| 
								 | 
							 
								| 
								 | 
								
									 
									Записан
								 | 
							  
							 
							
						 | 
					 
				 
			 |  
		 
	 | 
	 |