Главная - Литература

0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 [107] 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294

Используйте автоматические указатели auto ptr Если вы еще не выработали привычку использовать указатели auto ptr, займитесь этим! Удаляя занятую память автоматически при выходе auto ptr из области видимости, такие указатели решают множество проблем с утечками памяти, присущих обычным указателям. Книга «Моге Effective С++» Скотта Мейерса в правиле 9 содержит интересное обсуждение auto ptr (Meyers, 1996).

Изучите интеллектуальные указатели Интеллектуальные указатели - это замена обычных или «тупых» указателей (Meyers, 1996). Они действуют аналогично обычным, но предоставляют дополнительные возможности по управлению ресурсами, операциям копирования, присваивания, создания и удаления объектов. Перечисленные действия характерны для С++. Более полное обсуждение см. в правиле 28 книги «Моге Effective С++».

Указатели в С

Вот несколько советов по применению указателей, которые в особенности имеют отношение к языку С.

Используйте явный тип указателя вместо типа по умолчанию Язык С позволяет использовать указатели на char или void для любого типа переменной. Главное, что указатель куда-то указывает, и языку, в общем, не важно, на что именно. Но если вы используете явные типы для указателей, компилятор может выдавать предупреждение о несовпадающих типах указателей и некорректных преобразованиях. Если же явные типы не используются, он этого сделать не сможет. Старайтесь применять конкретные типы где только можно.

Из этого правила следует необходимость явного преобразования типа в тех случаях, когда нужно его изменить. Так, в этом фрагменте очевидно, что выделяется память для переменной типа NODE PTR:

Пример явного преобразования типа (С)

NodePtr = (NODE PTR) calloc( 1, sizeof( NODE ) );

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

Следуйте правилу звездочки при передаче параметров Вы можете получить значение аргумента из функции на языке С, только если в операции присваивания перед этим аргументом была указана звездочка (*). Многие программисты испытывают трудности при определении, когда С позволяет передавать значение обратно в вызывающий метод. Легко запомнить, что если вы указываете звездочку перед параметром, которому присваиваете значение, то это значение бу-



дет возвращено в вызывающий метод. Независимо от того, сколько звездочек вы указали в объявлении, для передачи значения в операторе присваивания должна быть хотя бы одна. Так, в следующем фрагменте значение, присвоенное переменной parameter, не будет передано в вызывающий метод, потому что операция присваивания не содержит звездочки:

Пример передачи параметра, который не будет работать (С)

void TryToPassBackAValue( int *parameter ) { parameter = SOME VALUE;

A здесь значение, присвоенное параметру parameter, будет возвращено, потому что перед parameter указана звездочка:

Пример передачи параметра, который сработает (С)

void TryToPassBackAValueC int *parameter ) { parameter = SOME VALUE;

Используйте sizeof 0 ля определения объема памяти, необходимой для размещения переменной Легче использовать sizeofQ, чем выяснять размер типа в справочнике. Кроме того, sizeofQ работает с вашими собственными структурами, которые в справочнике не описаны. Так как значение вычисляется в момент компиляции, то sizeofO не влияет на производительность. Кроме того, он переносим: перекомпиляция в другой среде автоматически изменяет размеры, вычисленные sizeofO- И еще он прост в сопровождении, поскольку при изменении используемого типа изменится и рассчитываемый размер.

13.3. Глобальные данные

1&щтшш бшш О разяй- Глобальные переменные доступны из любого места програм-тштшщгШтшуштту ь»- Иногда этот термин небрежно используют для обозна-т и дшныш шсса, ш. ад- чения переменных с более широкой областью видимости, раздел «Ошибочное пщтт чем локальные переменные, таких как классовые перемен-иие о данных класса как о то- jjj доступные во всех методах класса. Но сама по себе баяьиых данных* раздела 5J.

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

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

Даже если применение глобальных переменных не всегда ведет к ошибкам, оно все-таки вряд ли представляет собой хороший способ программирования.



Распространенные проблемы с глобальными данными

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

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

Непреднамеренные изменения глобальных данных Вы можете изменить значение глобальной переменной в одном месте и ошибочно думать, что оно осталось прежним где-то в другом. Такая проблема известна как «побочный эффект». Например, в этом фрагменте tbeAnswer является глобальной переменной:

Пример побочного эффекта (Visual Basic)

- theAnswer - глобальная переменная.

theAnswer - GetTheAnswer()

- GetOtherAnswerO изменяет theAnswer.

-otherAnswer = GetOtherAnswerO

- Значение averageAnswer неправильно.

averageAnswer = (theAnswer + otherAnswer) / 2

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

Причудливые и захватывающие проблемы при использовании псевдонимов для глобальных данных Использование псевдонима означает обращение к переменной по двум и более именам. Это происходит, когда глобальная переменная передается в метод, а там используется и в качестве глобальной переменной, и в качестве параметра. Вот пример метода, работающего с глобальной переменной:

Пример метода, подверженного проблеме с псевдонимами (Visual Basic)

Sub WriteGlobal( ByRef inputVar As Integer ) inputVar = 0

globalVar = inputVar + 5

MsgBox( "Input Variable: " & Str( inputVar ) ) MsgBox( "Global Variable: " & Str( globalVar ) ) End Sub



0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 [107] 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294



0.0064