Misc Flashcards

1
Q

How can you allow a member variable to be changed in a const qualified class?

A

Add “mutable” to declaration of variable.

Or make the member variable a pointer to the data (adheres to bitwise constness)

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
2
Q

How can you avoid code duplication bw const and non const versions of the same method?

A

Call the const version from the non const method by using const_cast and static_cast

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
3
Q

Give a few reasons to avoid #define

A
  • Preprocessor removes symbol name so debug is more cryptic
  • Doesn’t follow scoping
  • can result in multiple copies of value when a const guarantees only one
  • use enum if you don’t want the address of the const to be taken
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
4
Q
Why use explicit constructors?
explicit MyInt(const int x);
A
To avoid implicit type conversion. Like in:
MyInt myInt(3);
if (myInt == 3)...

The 3 can’t be implicitly converted to a MyInt if the conductor is declared explicit. Otherwise you could get undefined behavior

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
5
Q

Why is an initializer list preferable to assigning values in the constructor?

A

It’s more efficient and avoids possibly uninitialized members. Constructors without an initializer list will call the default constructors for each member, then assignments my call additional constructors. For built in data types, there could be undefined behavior

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
6
Q

What is a translation unit?

What’s the problem with multiple non-local static objects defined in different translation units? What’s the solution?

A

The source code resulting in a single object file. Usually a cpp file and it’s includes.

If one non-local static object uses another from a different translation unit, it could be undefined based on the order of initialization. The init order can’t be determined by design.

The solution is to wrap a non-local static object in a function - this results in a local static instead, which is guaranteed to be initialized when the fn is called. AKA “Singleton Pattern”

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
7
Q

When should you make destructors virtual?

In what situation should you avoid virtual fns altogether?

A

Only in polymorphic base classes. Without virtual, only the base class destructor is called if you have a reference to the base object (rather than derived)

In derived classes that are not themselves bases of another class. Also in small classes/structs where size is an issue (any virtual fn adds size to an instance bc of vtable pointer)

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
8
Q

What’s one reason never to inherit from STL string, containers, and possibly others?

A

They do not have virtual destructors.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
9
Q

Why should destructors never emit exceptions?

A

an instance going out of scope might throw, and the client would likely not have a chance to handle it.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
10
Q

If a destructor might throw (bc you must use something that could throw), what are a few options?
Pg 48

A
  1. Move the throwable action into a public function that the client may use in a try block. Then have a flag in object that checks to see if it was closed properly - if not, try it in the destructor.
  2. Perform the try in destructor and either swallow the exception or abort.
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
11
Q

How do you make assignment ops exception safe and self-assignment safe? Hint: the answer is not “if (this == &that)”
Pg 55

A

Order the operations such that if an op throws, the original object is unchanged.
Ex:

{
Obj *old = curr;
curr = new Obj() // might throw
delete old; // won’t get called if exception
return *this
}
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
12
Q

Can having more branches in the flow control decrease performance of the program?
Pg 56

A

Yes, bc if there are many possible avenues, instruction prefetching, caching, and pipelining will become less effective.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
13
Q

T/F: a compiler can make a copy operation more efficient in parameter passing compared to a copy in the body of function
Pg 57

A

True

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
14
Q

What’s a good choice for practicing RAII on an object that doesn’t need deletion on release?
Pg 64

A

A std::shared_ptr with a custom deleter that releases the resource instead of deleting.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
15
Q

What should you do with copy semantics of RAII objects?

P68

A

In general, disallow copying. But if you need to copy, either do a deep copy or reference counting to prevent multiple releases of the same resource

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
16
Q
How can you allow a client to use your RAII class as if it were the raw resource? Ex:
my_ptr x(new int(10));
doWork(x) // expects raw int*

Pg71

A

Provide an implicit conversion function!
operator int*() const
{ return rawResource; }

17
Q

What’s wrong with this code? Pg76

doWork(shared_ptr(new Obj), process())

A

C++ allows the compiler to order parameter calls in any order it chooses (for optimization). If new is called first, then process() 2nd and throws an exception, the shared pointer will never be constructed and you have a memory leak despite RAII intentions.

18
Q

What is the “cross DLL problem” regarding resource allocation/deallocation? What’s one way to prevent it?

A

If an object is created in one DLL with new, and deleted in another DLL with delete, there can be runtime errors.
Can prevent by using a shared_ptr with custom deleter (carries the deleter with it)

19
Q

Why is this interface error prone? What’s a good way to make this interface harder to use incorrectly? Pg 80

void Date(int day, int month, int year)

A

Int for each parameter invites invalid values (30 for month), switched values (Europe does month first) and even negatives.

Fix by using a small struct for each of day, month, and year. (Bring it into the type system)

struct month {
   month(int x) : val(x) {}
   static month Jan() { return month(1); }
   ...
}
// use methods instead of static vars because of Item 4 - non-local static objects across translation units
20
Q

What is the slicing problem? (polymorphic error)
How can you prevent it?
Pg 87

A

When a derived object is passed by VALUE as its base class type. Only the base class portion gets copied and unique qualities lost.

Prevent by passing by reference to const.

21
Q

When should you have public/protected data members in a class (according to the author)? Why?
Pg97

A

Never.

Making all members private allows class writer to:
Control access levels,
Enforce class invariants,
Change implementation without breaking client code
And it provides syntactic consistency.

22
Q

What is Argument Dependent Lookup (ADL), or Koenig Lookup?

Pg 110

A

For UNQUALIFIED function lookups (ie no “namespaceName::” before the fn name), C++ will prefer functions in the same namespace as the arguments, even if there is a std:: or other version visible in that scope.

That’s why the idiomatic

using std::swap
swap( obj1, obj2 )

…Is used. The using makes std::swap available as a fallback if there is no specialization for the “obj” types. Helpful for template fns where the type could be anything.

23
Q

When should you provide a custom swap fn?
How should you customize it for your classes?
Pg 112

A

Only if std::swap would be inefficient for your class (like in pimpl idiom).

  1. Provide a public swap member fn that efficiently swaps 2 instances of your class. NO THROW
  2. Also create a non-member swap in the same namespace as your class that calls the member.
  3. If it’s for a regular class (non template), also specialize std::swap. See item 25
  4. When calling swap, provide “using std::swap” then call swap without namespace qualification.
24
Q

How can this code be improved?

string s;
s = someConstString;

Pg 115

A

Bundle it into one call:

string s(someConstString);

This removes the assignment which isn’t free especially for large objects. It also moves the declaration of s to as late as possible

25
For a loop, is it better to declare a variable (that will change every iteration) before or inside the loop? Pg 116
In general, inside is better. Built-in types for example. UNLESS assignment to the variable is cheaper than a ctor/dtor pair. Inside also respects variable scoping better.
26
List a few things to consider with casting. Pg 123
Avoid it if you can. Especially dynamic_cast which is slow and can do things you don’t intend If it’s necessary to cast, hide it in a function. Use c++ style explicit casts to c-style, eg: (double)x -> static_cast(x)