Should this be called some special case of object slicing? Should this be called some special case of object slicing? arrays arrays

Should this be called some special case of object slicing?


It is not slicing at all, rather it is undefined behavior because you are accessing a Derived object where none exists (unless you get lucky and the sizes line up, in which case it is still UB but might do something useful anyway).

It's a simple case of failed pointer arithmetic.


This is not object slicing.

As noted, indexing myArray does not cause object slicing, but results in undefined behavior caused by indexing into an array of Derived as if it were an array of Base.

A kind of "array decay bug".

The bug introduced at the assignment of new Derived[42] to myArray may be a variation of an array decay bug.

In a true instance of this type of bug, there is an actual array:

Derived x[42];Base *myArray = x;

The problem is introduced because an array of Derived decays into a pointer to Derived with value equal to the address of its first element. The decay allows the pointer assignment to work properly. This decay behavior is inherited from C, which was a language design feature to allow arrays to be "passed by reference".

This leads us to the even worse incarnation of this bug. This feature gives C and C++ semantics for arrays syntax that turn array function arguments into aliases for pointer arguments.

void foo (Base base_array[42]) {    //...}Derived d[42];foo(d);          // Boom.

However, new[] is actually an overloaded operator that returns a pointer to the beginning of the allocated array object. So it is not a true instance of array decay (even though the array allocator is used). However, the bug symptoms are the same, and the intention of new[] is to get an array of Derived.

Detecting and avoiding the bug.

Use a smart pointer.

This kind of problem can be avoided by using a smart pointer object instead of managing a raw pointer. For example, the analogous coding error with unique_ptr would look like:

std::unique_ptr<Base[]> myArray = new Derived[42];

This would yield a compile time error, because unique_ptrs constructor is explicit

Use a container, and maybe std::reference.

Alternatively, you could avoid using new[], and use std::vector<Derived>. Then, you would have forced yourself to design a different solution for sending this array to framework code that is only Base aware. Possibly, a template function.

void my_framework_code (Base &object) {    //...}template <typename DERIVED>void my_interface(std::vector<DERIVED> &v) {    for (...) {        my_framework_code(v[i]);    }}

Or, by using std::reference_wrapper<Base>.

std::vector<Derived> v(42);std::vector<std::reference_wrapper<Base>> myArray(v.begin(), v.end());


This is not object slicing in any way.

Object slicing is perfectly well defined by the C++ standard. It may be a violation of object-oriented design principles or whatever, but it is not a violation of C++ rules.

This code violates 5.7 [expr.add] paragraph 7:

For addition or subtraction, if the expressions P or Q have type “pointer to cv T”, where T is different from the cv-unqualified array element type, the behavior is undefined. [Note: In particular, a pointer to a base class cannot be used for pointer arithmetic when the array contains objects of a derived class type. —end note].

Array subscript operator is defined to be equivalent to pointer arithmetic, 5.2.1 [expr.sub] paragraph 1:

The expression E1[E2] is identical (by definition) to *((E1)+(E2))