Articles & Books

Quick Q: Direct initialization with empty initializer list

Quick A: If there is an initializer list contructor, it will choose it.

Recently on SO:

Direct initialization with empty initializer list

When an argument is an initializer list ([dcl.init.list]), it is not an expression and special rules apply for converting it to a parameter type.

If the parameter type is std::initializer_list or “array of X” and all the elements of the initializer list can be implicitly converted to X, the implicit conversion sequence is the worst conversion necessary to convert an element of the list to X. This conversion can be a user-defined conversion even in the context of a call to an initializer-list constructor.

Otherwise, if the parameter is a non-aggregate class X and overload resolution per [over.match.list] chooses a single best constructor of X to perform the initialization of an object of type X from the argument initializer list, the implicit conversion sequence is a user-defined conversion sequence. If multiple constructors are viable but none is better than the others, the implicit conversion sequence is the ambiguous conversion sequence. User-defined conversions are allowed for conversion of the initializer list elements to the constructor parameter types except as noted in [over.best.ics].

Quick Q: Uses of destructor = delete;

Quick A: If you have an object which should never, ever be deleted or stored on the stack (automatic storage), or stored as part of another object, =delete will prevent all of these.

Recently on SO:

Uses of destructor = delete;

struct Handle {
  ~Handle()=delete;
};

struct Data {
  std::array<char,1024> buffer;
};

struct Bundle: Handle {
  Data data;
};

using bundle_storage = std::aligned_storage_t<sizeof(Bundle), alignof(Bundle)>;

std::size_t bundle_count = 0;
std::array< bundle_storage, 1000 > global_bundles;

Handle* get_bundle() {
  return new ((void*)global_bundles[bundle_count++]) Bundle();
}
void return_bundle( Handle* h ) {
  Assert( h == (void*)global_bundles[bundle_count-1] );
  --bundle_count;
}
char get_char( Handle const* h, std::size_t i ) {
  return static_cast<Bundle*>(h).data[i];
}
void set_char( Handle const* h, std::size_t i, char c ) {
  static_cast<Bundle*>(h).data[i] = c;
}

Here we have opaque Handles which may not be declared on the stack nor dynamically allocated. We have a system to get them from a known array.

I believe nothing above is undefined behavior; failing to destroy a Bundle is acceptable, as is creating a new one in its place.

And the interface doesn't have to expose how Bundle works. Just an opaque Handle.

Now this technique can be useful if other parts of the code need to know that all Handles are in that specific buffer, or their lifetime is tracked in specific ways. Possibly this could also be handled with private constructors and friend factory functions.

Why it is important to check what the malloc function returned

Unfortunately, many programmers are careless about checking of pointers, and sometimes they deliberately do not check whether to memory was allocated or not.

Why it is important to check what the malloc function returned

by Andrey Karpov

From the article:

There are 4 reasons at once, each of them is enough to prove that it is so necessary to write a check after you call the malloc function. If someone from your team doesn't write the checks, make him read this article.

  1. Null pointer dereference is undefined behavior
  2. Null pointer dereference is a vulnerability
  3. Where are guarantees that dereferencing of exactly a null pointer will occur?
  4. Where are the guarantees that memset fills the memory in a direct order?

The Most Vexing Parse: How to Spot It and Fix It Quickly--Jonathan Boccara

Did you have that problem?

The Most Vexing Parse: How to Spot It and Fix It Quickly

by Jonathan Boccara

From the article:

Everyone has their little defaults. You know, that little something that they do from time to time and that gets on your nerves, even though they’re otherwise nice people?

For C++, one of these little annoyances is the most vexing parse, well, as its name suggests...

Help the compiler warn you

And make less mistakes.

Help the compiler warn you

by Andrzej Krzemieński

From the article:

Compiler warnings are a very useful tool for detecting bugs in your program. Because you can enable them selectively, and because you can choose to turn them into hard errors on your compiler, you can in fact build a dialect, which is a safer subset of C++...

break and fallthrough--Andrey Karpov

A classic error:

break and fallthrough

by Andrey Karpov

From the article:

We would like to suggest reading the series of articles dedicated to the recommendations on writing code of high quality using the examples of errors found in the Chromium project. This is the second part, which will be devoted to the switch operator and, more precisely, to the problem of a forgotten break operator...

Guidelines for constructor and cast design--Jonathan Müller

Interesting indeed!

Guidelines for constructor and cast design

by Jonathan Müller

From the article:

A while back — but sadly not too many blog posts ago — I wrote about explicit constructors and how to handle assignment. In this blog post, I made the assumption that you most likely want to have explicit single argument constructors.

But when do we actually want implicit single argument constructors?

Let’s consider the broader question: How should I design a cast operation for my user-defined type? And how should I design a constructor?

But first, something different: what is the difference between a cast and a constructor?

Do compilers take inline as a hint?--Simon Brand

Isn't that a good question?

Do compilers take inline as a hint?

by Simon Brand

From the article:

If you’ve spent any time in C or C++ communities online, you’ve probably seen someone say this:

inline used to be a hint for compilers to inline the definition, but no compilers actually take that into account any more.

You shouldn’t believe everything you see on the internet...

Producer-consumer with buffer swapping -- Krzysztof Ostrowski

Synchronisation cost minimisation technique explained based on the classic producer-consumer problem.

Lock less with swapped buffers

by Krzysztof Ostrowski

From the article:

Presented approach keeps the shared resource synchronised, but unblocks the producer execution for the time of the buffer items' consumption to achieve significant gain in overall performance of the solution and its reliability.

Abseil's String Utility APIs -- Tom Manshreck

Abseil's C++ Tips of the Week for January 26th

Abseil's String Utility APIs

by Tom Manshreck, Abseil Tech Writer

About the article:

Abseil provides many important string utilities such as StrCat(), StrSplit() and StrJoin(). Read the tips that introduced these APIs at Google and explain how to use them now at https://abseil.io/tips/3  https://abseil.io/tips/10 , https://abseil.io/tips/36  and https://abseil.io/tips/59.