welcome to introduction to object-oriented programming (oop)€¦ · c++ uses const to eliminate...

97
QUIZ What (if anything) is wrong with this code?

Upload: others

Post on 07-Jul-2020

3 views

Category:

Documents


0 download

TRANSCRIPT

QUIZ What (if anything) is wrong with this code?

QUIZ What (if anything) is wrong with this code?

The value of the default argument should be placed in only one of the two (either one)!

Ch. 8: Constants

BUFSIZE is a name that only exists during preprocessing, therefore it doesn’t occupy storage and can be placed in a header file to provide a single value for all translation units that use it.

Most of the time, BUFSIZE will behave like an ordinary variable, but not all the time. In addition, there’s no type information. This can hide bugs that are very difficult to find.

C++ uses const to eliminate these problems by bringing value substitution into the domain of the compiler:

You can use bufsize anyplace where the compiler must know the value at compile time. The compiler can use bufsize to perform constant folding, which means the compiler will reduce a complicated constant expression to a simple one by performing the necessary calculations at compile time.

Important difference from C:

Because of subtle bugs that the preprocessor might introduce, you should always use const instead of #define value substitution in C++.

const in header files A const in C++ defaults to internal linkage; that is, it is visible only within the file where it is defined and cannot be seen at link time by other translation units.

You must always assign a value to a const when you define it, except when you make an explicit declaration using extern:

Normally, the C++ compiler avoids creating storage for a const, but instead holds the definition in its symbol table.

When you use extern with const, however, you force storage to be allocated. This is also true for certain other cases, such as:

• taking the address of a const

• complicated structs.

With built-in types, which are used in the majority of cases

involving constant expressions, the compiler can always

perform constant folding.

Safety consts

The use of const is not limited to replacing #defines.

If you initialize a variable with a value that is produced at runtime and you know it will not change for the lifetime of that variable, it is good programming practice to make it a const so the compiler will give you an error message if you accidentally try to change it.

Compile-time constants

Run-time constants

Aggregates

It’s possible to use const for aggregates, but you’re virtually assured that the compiler will not be sophisticated enough to keep an aggregate in its symbol table, so storage will be allocated.

In these situations, const means “a piece of storage that cannot be changed.” However, the value cannot be used at compile time because the compiler is not required to know the contents of the storage at compile time.

QUIZ Which statements are illegal?

QUIZ Which statements are illegal?

Read the subsection

Differences with C

Pointers Pointers can be made const.

• The compiler will still endeavor to prevent storage allocation and do constant folding when dealing with const pointers, but these features seem less useful in this case.

• More importantly, the compiler will tell you if you attempt to change a const pointer, which adds a great deal of safety.

When using const with pointers, there are two options:

• const can be applied to what the pointer is pointing to

• const can be applied to the address stored in the pointer itself.

Image source: http://webforce.blogspot.com/

Pointer to const vs. const pointer Compiler rule: const binds to the identifier closest to itself

int * u;

Compiler rule: const binds to the identifier closest to itself

int * u;

const int * u; int const * u;

int * const u; int * u const;

Legal, but not recommended. Data is constant. Data is constant.

Address is constant.

Illegal

int a = 42, b = 100; int * const u = &a; const int * v = &b;

When the address is constant, it has to be initialized when it is declared (Why?)

QUIZ Describe each pointer:

QUIZ Describe each pointer:

Both data and address are constant!

QUIZ Which statements are illegal?

QUIZ Which statements are illegal?

Formatting

int* u; int *u; or ?

int *u, *v, *w;

It only matters when we declare multiple pointers in one statement → The * is actually attached to the name of the pointer:

Assignment and type checking

C++ is very particular about type checking, and this extends to pointer assignments.

Assignment and type checking

You can assign the address of a non-const object to a const pointer because you’re simply promising not to change something that is OK to change.

Assignment and type checking

However, you can’t assign the address of a const object to a non-const pointer because then you’re saying you might change the object via the pointer.

You can use a cast to force such an assignment, but this is bad programming practice b/c you are then breaking the constness of the object, along with any safety promised by the const.

The problem of character array

literals

C.A.L. are arrays with constant data, so the correct declaration should be

Fix:

The compiler lets you get away with treating them as non-const because there’s so much existing C code that relies on this … but this works only in the declaration line!

If you want to be able to modify the string, put it in an array:

Source: ideone.com

We stop before the section

Function arguments & return values

EOL 21

Individual work for next time: End-of-chapter 1, 2, 4.

QUIZ What is constant folding?

The compiler can use bufsize to perform constant folding, which means the compiler will reduce a complicated constant expression to a simple one by performing the necessary calculations at compile time.

QUIZ What are the two benefits of using

const?

QUIZ What are the two benefits of using

const?

• insurance against inadvertent changes • allows the compiler to generate more efficient code by

eliminating storage and memory reads

QUIZ Will any multiplications be performed

at run-time in this program?

QUIZ Will this program compile correctly?

QUIZ Will this program compile correctly?

QUIZ Will this program compile correctly?

Can we “force” it (if we really wanted to)?

Extra-credit:

Function arguments & return values

QUIZ Do the same with a pointer

example

example

When the return type is one of the built-ins, this is the end of the story, since we’re not allowed to use the returned object as lvalue:

However, when the returned object is user-defined, in C++ it is allowed to use it as lvalue:

Remember from C that structs can be assigned to each other (unlike arrays)!

But, wait a second, what use could this be? Why does C++ even allow to use the returned object as lvalue?

A: It is the price to pay for references!

Non-const reference!

If we want to prevent this

modification, we make the return type

a const reference:

Read the subsection

Temporaries

SKIP the subsection

The “enum hack” in old code

Passing and returning addresses

“Whenever you’re passing an address into a function, you should make it a const if at all possible.

If you don’t, you’re excluding the possibility of using that function with anything that is a const.“

(b/c the C++ compiler won’t allow it)

example

Standard argument passing

“In C it’s very common to pass by value, and when you want to pass an address your only choice is to use a pointer.

However, neither of these approaches is preferred in C++. Instead, your first choice when passing an argument is to pass by reference, and by const reference at that.“

Advantages of passing by const reference

• “To the client programmer, the syntax is identical to that of passing by value, so there’s no confusion about pointers – they don’t even have to think about pointers.

• For the creator of the function, passing an address is virtually always more efficient than passing an entire class object

• If you pass by const reference it means your function will not change the destination of that address, so the effect from the client programmer’s point of view is exactly the same as pass-by-value.“

Read the end of this subsection, starting at

“Because of the syntax of references …”

(It’s another example with temporaries.)

We stop before the section Classes

QUIZ What is an lvalue?

QUIZ Compare C and C++: Is is possible to use

the value returned by a function as lvalue?

QUIZ Compare C and C++: Is is possible to use

the value returned by a function as lvalue?

Built-in data types (int, char, float, etc.) and any pointers

User-defined data types (struct, class, union) and any references

C No No

C++ No Yes

QUIZ Give a useful example of using the value

returned by a function as lvalue

Return type is non-const reference

QUIZ What is a temporary?

QUIZ Are temporaries const or non-const?

Explain why.

QUIZ Are temporaries const or non-const?

Explain why.

“[…] temporaries [are] automatically const. Because you usually won’t be able to get your hands on a temporary object, telling it to do something that will change that temporary is almost certainly a mistake because you won’t be able to use that information.

By making all temporaries automatically const, the compiler informs you when you make that mistake.”

Using const with classes

One of the places you’d like to use a const for constant expressions is inside classes.

Typical example: creating an array inside a class.

Typical example: creating an array inside a class:

• We want to use a const instead of a #define to establish the array size

• The array size is something we’d like to keep hidden inside the class, so if we used a name like size, we could use that name in another class without a clash.

• (Preprocessor treats all #defines as global!)

Problem:

Different objects of this class should be allowed to have different array sizes!

Thus, when we create an ordinary (non-static) const inside a class, we cannot give it an initial value.

This initialization must occur in the constructor, so each object instantiated can have its own value for the const.

Solution:

Inside the constructor, there is a special initialization point, called the constructor initializer list.

It is a list of “constructor calls” that occur after the function argument list, but before the opening brace of the constructor body.

example

This particular constructor has no executable

body

constructor initializer list

size is of type int, so it seems that we’re using a

constructor for a built-in type!

In the constructor initializer list, we can treat a built-in type as if it has a constructor.

In the constructor initializer list, we can treat a built-in type as if it has a constructor.

This rule works for const and non-const data members!

(But it is the only option for const!)

Practice:

In the constructor initializer list, we can treat a built-in type as if it has a constructor.

The convention was also extended for consistency to all built-in types:

Extra-credit:

Compile-time constants in classes

The static keyword inside a class means “there’s only one instance, regardless of how many objects of the class are created”

A static const of a built-in type can be treated as a compile-time constant.

static consts must be initialized when they are defined (all other data members must be initialized in the constructor or in other member functions)

example

User-defined types will be addressed soon!

This is a new “stack” class, not a continuation of the “stash”-and-”stack”

examples from prev. chapters

Initialized at the point of definition!

QUIZ

What is the exact data type for stack? Draw a memory diagram!

QUIZ What is the difference between these two definitions of stack? Use the diagram from the prev. quiz to explain!

SKIP the subsection

The “enum hack” in old code

const member functions

Preceding the function declaration with const means the return value is const! Instead, you must place the const specifier after the argument list.

const objects & member functions

Unlike the case of default arguments, const must be present in both function declaration and definition.

Practice:

But what exactly does it mean?

Since f( ) is a const member function, if it attempts to change i in any way or to call another member function that is not const, the compiler flags it as an error.

If an object of a class is declared const, then it is only legal to call const member functions of that class with the object.

const objects

example

The compiler does not look inside the

function!

SKIP the subsections

• mutable: bitwise vs. logical const

• ROMability

volatile The syntax of volatile is identical to that for const, but volatile means “This data may change outside the knowledge of the compiler.”

Somehow, the environment is changing the data (possibly through multitasking, multithreading or interrupts), and volatile tells the compiler not to make any assumptions about that data, especially during optimization.

volatile You can also create const volatile objects, which can’t be changed by the client programmer but instead change through some outside agency.

The syntax of volatile is identical to const, so discussions of the two are often treated together. The two are referred to in combination as the c-v qualifier.

Read the code example

C08:Volatile.cpp

and the explanations.

Homework for ch. 8

Provided as separate handout (also available on our webpage --> agapie.net)

Due Monday, Oct. 30, at the beginning of class.

Please hand in a hard-copy, do not email!

EOL 24