| 1 |
Ddoc |
|---|
| 2 |
|
|---|
| 3 |
$(D_S Const and Immutable, |
|---|
| 4 |
|
|---|
| 5 |
$(P When examining a data structure or interface, it is very |
|---|
| 6 |
helpful to be able to easily tell which data can be expected to not |
|---|
| 7 |
change, which data might change, and who may change that data. |
|---|
| 8 |
This is done with the aid of the language typing system. |
|---|
| 9 |
Data can be marked as const or immutable, with the default being |
|---|
| 10 |
changeable (or $(I mutable)). |
|---|
| 11 |
) |
|---|
| 12 |
|
|---|
| 13 |
$(P $(I immutable) applies to data that cannot change. |
|---|
| 14 |
Immutable data values, once constructed, remain the same for |
|---|
| 15 |
the duration of the program's |
|---|
| 16 |
execution. |
|---|
| 17 |
Immutable data can be placed in ROM (Read Only Memory) or in |
|---|
| 18 |
memory pages marked by the hardware as read only. |
|---|
| 19 |
Since immutable data does not change, it enables many opportunities |
|---|
| 20 |
for program optimization, and has applications in functional |
|---|
| 21 |
style programming. |
|---|
| 22 |
) |
|---|
| 23 |
|
|---|
| 24 |
$(P $(I const) applies to data that cannot be changed by |
|---|
| 25 |
the const reference to that data. It may, however, be changed |
|---|
| 26 |
by another reference to that same data. |
|---|
| 27 |
Const finds applications in passing data through interfaces |
|---|
| 28 |
that promise not to modify them. |
|---|
| 29 |
) |
|---|
| 30 |
|
|---|
| 31 |
$(P Both immutable and const are $(I transitive), which means |
|---|
| 32 |
that any data reachable through an immutable reference is also |
|---|
| 33 |
immutable, and likewise for const. |
|---|
| 34 |
) |
|---|
| 35 |
|
|---|
| 36 |
$(SECTION2 Immutable Storage Class, |
|---|
| 37 |
|
|---|
| 38 |
$(P |
|---|
| 39 |
The simplest immutable declarations use it as a storage class. |
|---|
| 40 |
It can be used to declare manifest constants. |
|---|
| 41 |
) |
|---|
| 42 |
|
|---|
| 43 |
--- |
|---|
| 44 |
immutable int x = 3; // x is set to 3 |
|---|
| 45 |
x = 4; // error, x is immutable |
|---|
| 46 |
char[x] s; // s is an array of 3 char's |
|---|
| 47 |
--- |
|---|
| 48 |
|
|---|
| 49 |
$(P The type can be inferred from the initializer: |
|---|
| 50 |
) |
|---|
| 51 |
--- |
|---|
| 52 |
immutable y = 4; // y is of type int |
|---|
| 53 |
y = 5; // error, y is immutable |
|---|
| 54 |
--- |
|---|
| 55 |
|
|---|
| 56 |
$(P If the initializer is not present, the immutable can |
|---|
| 57 |
be initialized from the corresponding constructor: |
|---|
| 58 |
) |
|---|
| 59 |
|
|---|
| 60 |
--- |
|---|
| 61 |
immutable int z; |
|---|
| 62 |
void test() |
|---|
| 63 |
{ |
|---|
| 64 |
z = 3; // error, z is immutable |
|---|
| 65 |
} |
|---|
| 66 |
static this() |
|---|
| 67 |
{ |
|---|
| 68 |
z = 3; // ok, can set immutable that doesn't have |
|---|
| 69 |
// static initializer |
|---|
| 70 |
} |
|---|
| 71 |
--- |
|---|
| 72 |
$(P |
|---|
| 73 |
The initializer for a non-local immutable declaration must be |
|---|
| 74 |
evaluatable |
|---|
| 75 |
at compile time: |
|---|
| 76 |
) |
|---|
| 77 |
|
|---|
| 78 |
--- |
|---|
| 79 |
int foo(int f) { return f * 3; } |
|---|
| 80 |
int i = 5; |
|---|
| 81 |
immutable x = 3 * 4; // ok, 12 |
|---|
| 82 |
immutable y = i + 1; // error, cannot evaluate at compile time |
|---|
| 83 |
immutable z = foo(2) + 1; // ok, foo(2) can be evaluated at compile time, 7 |
|---|
| 84 |
--- |
|---|
| 85 |
|
|---|
| 86 |
$(P The initializer for a non-static local immutable declaration |
|---|
| 87 |
is evaluated at run time: |
|---|
| 88 |
) |
|---|
| 89 |
--- |
|---|
| 90 |
int foo(int f) |
|---|
| 91 |
{ |
|---|
| 92 |
immutable x = f + 1; // evaluated at run time |
|---|
| 93 |
x = 3; // error, x is immutable |
|---|
| 94 |
} |
|---|
| 95 |
--- |
|---|
| 96 |
|
|---|
| 97 |
$(P |
|---|
| 98 |
Because immutable is transitive, data referred to by an immutable is |
|---|
| 99 |
also immutable: |
|---|
| 100 |
) |
|---|
| 101 |
|
|---|
| 102 |
--- |
|---|
| 103 |
immutable char[] s = "foo"; |
|---|
| 104 |
s[0] = 'a'; // error, s refers to immutable data |
|---|
| 105 |
s = "bar"; // error, s is immutable |
|---|
| 106 |
--- |
|---|
| 107 |
|
|---|
| 108 |
$(P Immutable declarations can appear as lvalues, i.e. they can |
|---|
| 109 |
have their address taken, and occupy storage. |
|---|
| 110 |
) |
|---|
| 111 |
) |
|---|
| 112 |
|
|---|
| 113 |
$(SECTION2 Const Storage Class, |
|---|
| 114 |
|
|---|
| 115 |
$(P |
|---|
| 116 |
A const declaration is exactly like an immutable declaration, |
|---|
| 117 |
with the following differences: |
|---|
| 118 |
) |
|---|
| 119 |
|
|---|
| 120 |
$(UL |
|---|
| 121 |
$(LI Any data referenced by the const declaration cannot be |
|---|
| 122 |
changed from the const declaration, but it might be changed |
|---|
| 123 |
by other references to the same data.) |
|---|
| 124 |
|
|---|
| 125 |
$(LI The type of a const declaration is itself const.) |
|---|
| 126 |
) |
|---|
| 127 |
|
|---|
| 128 |
$(COMMENT |
|---|
| 129 |
$(TABLE1 |
|---|
| 130 |
|
|---|
| 131 |
$(TR $(TH ) $(TH AddrOf) $(TH CTFEInit) $(TH Static) $(TH Field) $(TH Stack) $(TH Ctor)) |
|---|
| 132 |
|
|---|
| 133 |
$(TR $(TD ) |
|---|
| 134 |
$(TD Can the address be taken?) |
|---|
| 135 |
$(TD Is compile time function evaluation done on the initializer?) |
|---|
| 136 |
$(TD allocated as static data?) |
|---|
| 137 |
$(TD allocated as a per-instance field?) |
|---|
| 138 |
$(TD allocated on the stack?) |
|---|
| 139 |
$(TD Can the variable be assigned to in a constructor?) |
|---|
| 140 |
) |
|---|
| 141 |
|
|---|
| 142 |
|
|---|
| 143 |
$(TR $(TH Global data)) |
|---|
| 144 |
|
|---|
| 145 |
$(TR $(TD1 const T x;) $(Y) $(N) $(Y) $(N) $(N) $(Y)) |
|---|
| 146 |
$(TR $(TD1 const T x = 3;) $(N) $(Y) $(N) $(N) $(N) $(N)) |
|---|
| 147 |
$(TR $(TD1 static const T x;) $(Y) $(N) $(Y) $(N) $(N) $(Y)) |
|---|
| 148 |
$(TR $(TD1 static const T x = 3;) $(Y) $(Y) $(Y) $(N) $(N) $(N)) |
|---|
| 149 |
|
|---|
| 150 |
|
|---|
| 151 |
$(TR $(TH Class Members)) |
|---|
| 152 |
|
|---|
| 153 |
$(TR $(TD1 const T x;) $(Y) $(N) $(N) $(Y) $(N) $(Y)) |
|---|
| 154 |
$(TR $(TD1 const T x = 3;) $(N) $(Y) $(N) $(N) $(N) $(N)) |
|---|
| 155 |
$(TR $(TD1 static const T x;) $(Y) $(N) $(Y) $(N) $(N) $(Y)) |
|---|
| 156 |
$(TR $(TD1 static const T x = 3;) $(Y) $(Y) $(Y) $(N) $(N) $(N)) |
|---|
| 157 |
|
|---|
| 158 |
|
|---|
| 159 |
$(TR $(TH Local Variables)) |
|---|
| 160 |
|
|---|
| 161 |
$(TR $(TD1 const T x;) $(Y) $(Y) $(N) $(N) $(Y) $(N)) |
|---|
| 162 |
$(TR $(TD1 const T x = 3;) $(Y) $(N) $(N) $(N) $(Y) $(N)) |
|---|
| 163 |
$(TR $(TD1 static const T x;) $(Y) $(Y) $(Y) $(N) $(N) $(N)) |
|---|
| 164 |
$(TR $(TD1 static const T x = 3;) $(Y) $(Y) $(Y) $(N) $(N) $(N)) |
|---|
| 165 |
|
|---|
| 166 |
$(TR $(TH Function Parameters)) |
|---|
| 167 |
|
|---|
| 168 |
$(TR $(TD1 const T x;) $(Y) $(N) $(N) $(N) $(Y) $(N)) |
|---|
| 169 |
) |
|---|
| 170 |
|
|---|
| 171 |
|
|---|
| 172 |
$(P Notes:) |
|---|
| 173 |
|
|---|
| 174 |
$(OL |
|---|
| 175 |
$(LI If CTFEInit is true, then the initializer can also be used for |
|---|
| 176 |
constant folding.) |
|---|
| 177 |
) |
|---|
| 178 |
|
|---|
| 179 |
|
|---|
| 180 |
$(TABLE1 |
|---|
| 181 |
<caption>Template Argument Deduced Type</caption> |
|---|
| 182 |
$(TR $(TH ) $(TH mutable $(CODE T)) $(TH1 const(T)) $(TH1 immutable(T))) |
|---|
| 183 |
$(TR $(TD1 foo(U)) $(TDE T) $(TDE T) $(TDE T)) |
|---|
| 184 |
$(TR $(TD1 foo(U:U)) $(TDE T) $(TDE const(T)) $(TDE immutable(T))) |
|---|
| 185 |
$(TR $(TD1 foo(U:const(U))) $(TDI T) $(TDE T) $(TDI T)) |
|---|
| 186 |
$(TR $(TD1 foo(U:immutable(U))) $(NM) $(NM) $(TDE T)) |
|---|
| 187 |
) |
|---|
| 188 |
|
|---|
| 189 |
$(P Where:) |
|---|
| 190 |
|
|---|
| 191 |
$(TABLE1 |
|---|
| 192 |
$(TR $(TD $(GREEN green)) $(TD exact match)) |
|---|
| 193 |
$(TR $(TD $(ORANGE orange)) $(TD implicit conversion)) |
|---|
| 194 |
) |
|---|
| 195 |
) |
|---|
| 196 |
) |
|---|
| 197 |
|
|---|
| 198 |
$(SECTION2 Immutable Type, |
|---|
| 199 |
|
|---|
| 200 |
$(P |
|---|
| 201 |
Data that will never change its value can be typed as immutable. |
|---|
| 202 |
The immutable keyword can be used as a $(I type constructor): |
|---|
| 203 |
) |
|---|
| 204 |
|
|---|
| 205 |
--- |
|---|
| 206 |
immutable(char)[] s = "hello"; |
|---|
| 207 |
--- |
|---|
| 208 |
|
|---|
| 209 |
$(P |
|---|
| 210 |
The immutable applies to the type within the following parentheses. |
|---|
| 211 |
So, while $(CODE s) can be assigned new values, |
|---|
| 212 |
the contents of $(CODE s[]) cannot be: |
|---|
| 213 |
) |
|---|
| 214 |
|
|---|
| 215 |
--- |
|---|
| 216 |
s[0] = 'b'; // error, s[] is immutable |
|---|
| 217 |
s = null; // ok, s itself is not immutable |
|---|
| 218 |
--- |
|---|
| 219 |
|
|---|
| 220 |
$(P |
|---|
| 221 |
Immutableness is transitive, meaning it applies to anything that |
|---|
| 222 |
can be referenced from the immutable type: |
|---|
| 223 |
) |
|---|
| 224 |
|
|---|
| 225 |
--- |
|---|
| 226 |
immutable(char*)** p = ...; |
|---|
| 227 |
p = ...; // ok, p is not immutable |
|---|
| 228 |
*p = ...; // ok, *p is not immutable |
|---|
| 229 |
**p = ...; // error, **p is immutable |
|---|
| 230 |
***p = ...; // error, ***p is immutable |
|---|
| 231 |
--- |
|---|
| 232 |
|
|---|
| 233 |
$(P Immutable used as a storage class is equivalent to using |
|---|
| 234 |
immutable as a type constructor for the entire type of a |
|---|
| 235 |
declaration:) |
|---|
| 236 |
|
|---|
| 237 |
--- |
|---|
| 238 |
immutable int x = 3; // x is typed as immutable(int) |
|---|
| 239 |
immutable(int) y = 3; // y is immutable |
|---|
| 240 |
--- |
|---|
| 241 |
) |
|---|
| 242 |
|
|---|
| 243 |
|
|---|
| 244 |
$(SECTION2 Creating Immutable Data, |
|---|
| 245 |
|
|---|
| 246 |
$(P |
|---|
| 247 |
The first way is to use a literal that is already immutable, |
|---|
| 248 |
such as string literals. String literals are always immutable. |
|---|
| 249 |
) |
|---|
| 250 |
|
|---|
| 251 |
--- |
|---|
| 252 |
auto s = "hello"; // s is immutable(char)[5] |
|---|
| 253 |
char[] p = "world"; // error, cannot implicitly convert immutable |
|---|
| 254 |
// to mutable |
|---|
| 255 |
--- |
|---|
| 256 |
|
|---|
| 257 |
$(P |
|---|
| 258 |
The second way is to cast data to immutable. |
|---|
| 259 |
When doing so, it is up to the programmer to ensure that no |
|---|
| 260 |
other mutable references to the same data exist. |
|---|
| 261 |
) |
|---|
| 262 |
|
|---|
| 263 |
--- |
|---|
| 264 |
char[] s = ...; |
|---|
| 265 |
immutable(char)[] p = cast(immutable)s; // undefined behavior |
|---|
| 266 |
immutable(char)[] p = cast(immutable)s.dup; // ok, unique reference |
|---|
| 267 |
--- |
|---|
| 268 |
|
|---|
| 269 |
$(P |
|---|
| 270 |
The $(CODE .idup) property is a convenient way to create an immutable |
|---|
| 271 |
copy of an array: |
|---|
| 272 |
) |
|---|
| 273 |
|
|---|
| 274 |
--- |
|---|
| 275 |
auto p = s.idup; |
|---|
| 276 |
p[0] = ...; // error, p[] is immutable |
|---|
| 277 |
--- |
|---|
| 278 |
|
|---|
| 279 |
<h2>Removing Immutable With A Cast</h2> |
|---|
| 280 |
|
|---|
| 281 |
$(P |
|---|
| 282 |
The immutable type can be removed with a cast: |
|---|
| 283 |
) |
|---|
| 284 |
|
|---|
| 285 |
--- |
|---|
| 286 |
immutable int* p = ...; |
|---|
| 287 |
int* q = cast(int*)p; |
|---|
| 288 |
--- |
|---|
| 289 |
|
|---|
| 290 |
$(P |
|---|
| 291 |
This does not mean, however, that one can change the data: |
|---|
| 292 |
) |
|---|
| 293 |
|
|---|
| 294 |
--- |
|---|
| 295 |
*q = 3; // allowed by compiler, but result is undefined behavior |
|---|
| 296 |
--- |
|---|
| 297 |
|
|---|
| 298 |
$(P |
|---|
| 299 |
The ability to cast away immutable-correctness is necessary in |
|---|
| 300 |
some cases where the static typing is incorrect and not fixable, such |
|---|
| 301 |
as when referencing code in a library one cannot change. |
|---|
| 302 |
Casting is, as always, a blunt and effective instrument, and |
|---|
| 303 |
when using it to cast away immutable-correctness, one must assume |
|---|
| 304 |
the responsibility to ensure the immutableness of the data, as |
|---|
| 305 |
the compiler will no longer be able to statically do so. |
|---|
| 306 |
) |
|---|
| 307 |
) |
|---|
| 308 |
|
|---|
| 309 |
|
|---|
| 310 |
$(SECTION2 Immutable Member Functions, |
|---|
| 311 |
|
|---|
| 312 |
$(P |
|---|
| 313 |
Immutable member functions are guaranteed that the object |
|---|
| 314 |
and anything referred to by the $(CODE this) reference is immutable. |
|---|
| 315 |
They are declared as: |
|---|
| 316 |
) |
|---|
| 317 |
|
|---|
| 318 |
--- |
|---|
| 319 |
struct S |
|---|
| 320 |
{ int x; |
|---|
| 321 |
|
|---|
| 322 |
immutable void foo() |
|---|
| 323 |
{ |
|---|
| 324 |
x = 4; // error, x is immutable |
|---|
| 325 |
this.x = 4; // error, x is immutable |
|---|
| 326 |
} |
|---|
| 327 |
--- |
|---|
| 328 |
|
|---|
| 329 |
$(P The $(D_KEYWORD const) and $(D_KEYWORD immutable) function |
|---|
| 330 |
attributes |
|---|
| 331 |
can also appear after the closing parenthesis of |
|---|
| 332 |
the parameter list: |
|---|
| 333 |
) |
|---|
| 334 |
|
|---|
| 335 |
--- |
|---|
| 336 |
struct S |
|---|
| 337 |
{ |
|---|
| 338 |
void bar() immutable |
|---|
| 339 |
{ |
|---|
| 340 |
} |
|---|
| 341 |
} |
|---|
| 342 |
--- |
|---|
| 343 |
) |
|---|
| 344 |
|
|---|
| 345 |
|
|---|
| 346 |
$(SECTION2 Const Type, |
|---|
| 347 |
|
|---|
| 348 |
$(P |
|---|
| 349 |
Const types are like immutable types, except that const |
|---|
| 350 |
forms a read-only $(I view) of data. Other aliases to that |
|---|
| 351 |
same data may change it at any time. |
|---|
| 352 |
) |
|---|
| 353 |
) |
|---|
| 354 |
|
|---|
| 355 |
|
|---|
| 356 |
$(SECTION2 Const Member Functions, |
|---|
| 357 |
|
|---|
| 358 |
$(P |
|---|
| 359 |
Const member functions are functions that are not allowed to |
|---|
| 360 |
change any part of the object through the member function's |
|---|
| 361 |
this reference. |
|---|
| 362 |
) |
|---|
| 363 |
) |
|---|
| 364 |
|
|---|
| 365 |
|
|---|
| 366 |
$(SECTION2 Implicit Conversions, |
|---|
| 367 |
|
|---|
| 368 |
$(P |
|---|
| 369 |
Mutable and immutable types can be implicitly converted to const. |
|---|
| 370 |
Mutable types cannot be implicitly converted to immutable, |
|---|
| 371 |
and vice versa. |
|---|
| 372 |
) |
|---|
| 373 |
) |
|---|
| 374 |
|
|---|
| 375 |
|
|---|
| 376 |
$(SECTION2 Comparing D Immutable and Const with C++ Const, |
|---|
| 377 |
|
|---|
| 378 |
<table border=2 cellpadding=4 cellspacing=0 class="comp"> |
|---|
| 379 |
<caption>Const, Immutable Comparison</caption> |
|---|
| 380 |
|
|---|
| 381 |
<thead> |
|---|
| 382 |
$(TR |
|---|
| 383 |
$(TH Feature) |
|---|
| 384 |
$(TH D) |
|---|
| 385 |
$(TH C++98) |
|---|
| 386 |
) |
|---|
| 387 |
</thead> |
|---|
| 388 |
|
|---|
| 389 |
<tbody> |
|---|
| 390 |
|
|---|
| 391 |
$(TR |
|---|
| 392 |
$(TD const keyword) |
|---|
| 393 |
$(TD Yes) |
|---|
| 394 |
$(TD Yes) |
|---|
| 395 |
) |
|---|
| 396 |
|
|---|
| 397 |
$(TR |
|---|
| 398 |
$(TD immutable keyword) |
|---|
| 399 |
$(TD Yes) |
|---|
| 400 |
$(TD No) |
|---|
| 401 |
) |
|---|
| 402 |
|
|---|
| 403 |
$(TR |
|---|
| 404 |
$(TD const notation) |
|---|
| 405 |
$(TD Functional: |
|---|
| 406 |
--- |
|---|
| 407 |
//ptr to const ptr to const int |
|---|
| 408 |
const(int*)* p; |
|---|
| 409 |
--- |
|---|
| 410 |
) |
|---|
| 411 |
$(TD Postfix: |
|---|
| 412 |
$(CPPCODE |
|---|
| 413 |
//ptr to const ptr to const int |
|---|
| 414 |
const int *const *p; |
|---|
| 415 |
) |
|---|
| 416 |
) |
|---|
| 417 |
) |
|---|
| 418 |
|
|---|
| 419 |
$(TR |
|---|
| 420 |
$(TD transitive const) |
|---|
| 421 |
$(TD Yes: |
|---|
| 422 |
--- |
|---|
| 423 |
//const ptr to const ptr to const int |
|---|
| 424 |
const int** p; |
|---|
| 425 |
**p = 3; // error |
|---|
| 426 |
--- |
|---|
| 427 |
) |
|---|
| 428 |
$(TD No: |
|---|
| 429 |
$(CPPCODE |
|---|
| 430 |
// const ptr to ptr to int |
|---|
| 431 |
int** const p; |
|---|
| 432 |
**p = 3; // ok |
|---|
| 433 |
) |
|---|
| 434 |
) |
|---|
| 435 |
) |
|---|
| 436 |
|
|---|
| 437 |
$(TR |
|---|
| 438 |
$(TD cast away const) |
|---|
| 439 |
$(TD Yes: |
|---|
| 440 |
--- |
|---|
| 441 |
// ptr to const int |
|---|
| 442 |
const(int)* p; |
|---|
| 443 |
int* q = cast(int*)p; // ok |
|---|
| 444 |
--- |
|---|
| 445 |
) |
|---|
| 446 |
$(TD Yes: |
|---|
| 447 |
$(CPPCODE |
|---|
| 448 |
// ptr to const int |
|---|
| 449 |
const int* p; |
|---|
| 450 |
int* q = const_cast<int*>p; //ok |
|---|
| 451 |
) |
|---|
| 452 |
) |
|---|
| 453 |
) |
|---|
| 454 |
|
|---|
| 455 |
$(TR |
|---|
| 456 |
$(TD modification after casting away const) |
|---|
| 457 |
$(TD No: |
|---|
| 458 |
--- |
|---|
| 459 |
// ptr to const int |
|---|
| 460 |
const(int)* p; |
|---|
| 461 |
int* q = cast(int*)p; |
|---|
| 462 |
*q = 3; // undefined behavior |
|---|
| 463 |
--- |
|---|
| 464 |
) |
|---|
| 465 |
$(TD Yes: |
|---|
| 466 |
$(CPPCODE |
|---|
| 467 |
// ptr to const int |
|---|
| 468 |
const int* p; |
|---|
| 469 |
int* q = const_cast<int*>p; |
|---|
| 470 |
*q = 3; // ok |
|---|
| 471 |
) |
|---|
| 472 |
) |
|---|
| 473 |
) |
|---|
| 474 |
|
|---|
| 475 |
$(TR |
|---|
| 476 |
$(TD overloading of top level const) |
|---|
| 477 |
$(TD Yes: |
|---|
| 478 |
--- |
|---|
| 479 |
void foo(int x); |
|---|
| 480 |
void foo(const int x); //ok |
|---|
| 481 |
--- |
|---|
| 482 |
) |
|---|
| 483 |
$(TD No: |
|---|
| 484 |
$(CPPCODE |
|---|
| 485 |
void foo(int x); |
|---|
| 486 |
void foo(const int x); //error |
|---|
| 487 |
) |
|---|
| 488 |
) |
|---|
| 489 |
) |
|---|
| 490 |
|
|---|
| 491 |
$(TR |
|---|
| 492 |
$(TD aliasing of const with mutable) |
|---|
| 493 |
$(TD Yes: |
|---|
| 494 |
--- |
|---|
| 495 |
void foo(const int* x, int* y) |
|---|
| 496 |
{ |
|---|
| 497 |
bar(*x); // bar(3) |
|---|
| 498 |
*y = 4; |
|---|
| 499 |
bar(*x); // bar(4) |
|---|
| 500 |
} |
|---|
| 501 |
... |
|---|
| 502 |
int i = 3; |
|---|
| 503 |
foo(&i, &i); |
|---|
| 504 |
--- |
|---|
| 505 |
) |
|---|
| 506 |
$(TD Yes: |
|---|
| 507 |
$(CPPCODE |
|---|
| 508 |
void foo(const int* x, int* y) |
|---|
| 509 |
{ |
|---|
| 510 |
bar(*x); // bar(3) |
|---|
| 511 |
*y = 4; |
|---|
| 512 |
bar(*x); // bar(4) |
|---|
| 513 |
} |
|---|
| 514 |
... |
|---|
| 515 |
int i = 3; |
|---|
| 516 |
foo(&i, &i); |
|---|
| 517 |
) |
|---|
| 518 |
) |
|---|
| 519 |
) |
|---|
| 520 |
|
|---|
| 521 |
$(TR |
|---|
| 522 |
$(TD aliasing of immutable with mutable) |
|---|
| 523 |
$(TD No: |
|---|
| 524 |
--- |
|---|
| 525 |
void foo(immutable int* x, int* y) |
|---|
| 526 |
{ |
|---|
| 527 |
bar(*x); // bar(3) |
|---|
| 528 |
*y = 4; // undefined behavior |
|---|
| 529 |
bar(*x); // bar(??) |
|---|
| 530 |
} |
|---|
| 531 |
... |
|---|
| 532 |
int i = 3; |
|---|
| 533 |
foo(cast(immutable)&i, &i); |
|---|
| 534 |
--- |
|---|
| 535 |
) |
|---|
| 536 |
$(TD No immutables) |
|---|
| 537 |
) |
|---|
| 538 |
|
|---|
| 539 |
$(TR |
|---|
| 540 |
$(TD type of string literal) |
|---|
| 541 |
$(TD immutable(char)[]) |
|---|
| 542 |
$(TD const char*) |
|---|
| 543 |
) |
|---|
| 544 |
|
|---|
| 545 |
|
|---|
| 546 |
$(TR |
|---|
| 547 |
$(TD implicit conversion of string literal to non-const) |
|---|
| 548 |
$(TD not allowed) |
|---|
| 549 |
$(TD allowed, but deprecated) |
|---|
| 550 |
) |
|---|
| 551 |
|
|---|
| 552 |
</tbody> |
|---|
| 553 |
</table> |
|---|
| 554 |
) |
|---|
| 555 |
|
|---|
| 556 |
|
|---|
| 557 |
) |
|---|
| 558 |
|
|---|
| 559 |
Macros: |
|---|
| 560 |
TH1=<th nowrap="nowrap">$(CODE $0)</th> |
|---|
| 561 |
TD1=<td nowrap="nowrap">$(CODE $0)</td> |
|---|
| 562 |
TDE=<td nowrap="nowrap">$(GREEN $(CODE $0))</td> |
|---|
| 563 |
TDI=<td nowrap="nowrap">$(ORANGE $(CODE $0))</td> |
|---|
| 564 |
NM=$(TD $(RED no match)) |
|---|
| 565 |
Y=$(TD $(GREEN Yes)) |
|---|
| 566 |
N=$(TD $(RED No)) |
|---|
| 567 |
TITLE=Const and Immutable |
|---|
| 568 |
WIKI=ConstInvariant |
|---|
| 569 |
NO=<td class="compNo">No</td> |
|---|
| 570 |
NO1=<td class="compNo"><a href="$1">No</a></td> |
|---|
| 571 |
YES=<td class="compYes">Yes</td> |
|---|
| 572 |
YES1=<td class="compYes"><a href="$1">Yes</a></td> |
|---|
| 573 |
D_CODE = <pre class="d_code2">$0</pre> |
|---|
| 574 |
CPPCODE2 = <pre class="cppcode2">$0</pre> |
|---|
| 575 |
ERROR = $(RED $(B error)) |
|---|
| 576 |
COMMA=, |
|---|
| 577 |
META_KEYWORDS=D Programming Language, const, immutable |
|---|
| 578 |
META_DESCRIPTION=Comparison of const between the |
|---|
| 579 |
D programming language, C++, and C++0x |
|---|