c++ 这应该被称为对象切片的一些特殊情况吗?

让我们说,我有一个类派生从类Base,而sizeof(Derived)> sizeof(Base)。现在,如果像这样分配一个Derived数组:

Base * myArray = new Derived[42];

然后尝试使用访问第n个对象

doSomethingWithBase(myArray[n]);

然后这可能(但不总是)导致未定义的行为,由于访问Base从一个无效的位置。

这种编程错误的正确术语是什么?是否应考虑object slicing的情况?

这不是对象切片。

如上所述,索引myArray不会导致对象切片,但导致未定义的行为导致索引到Derived数组,就像它是一个Base数组。

一种“阵列衰变bug”。

在将Derived [42]分配给myArray时引入的错误可能是阵列衰减错误的变体。

在这种类型的bug的真实例子中,有一个实际的数组:

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

引入该问题的原因是Derived数组衰减为Derived的指针,其值等于其第一个元素的地址。衰减允许指针分配正常工作。这种衰减行为是继承自C,这是一个语言设计功能,允许数组“通过引用传递”。

这导致我们更糟的这个bug的化身。这个特性给出了数组语法的C和C语义,它将数组函数参数转换为指针参数的别名。

void foo (Base base_array[42]) {
    //...
}

Derived d[42];
foo(d);          // Boom.

但是,new []实际上是一个重载的操作符,它返回一个指向所分配的数组对象开头的指针。所以它不是一个真正的阵列衰减实例(即使使用数组分配器)。然而,bug的症状是一样的,新的[]的意图是得到一个Derived数组。

检测和避免错误。

使用智能指针。

这种问题可以通过使用智能指针对象而不是管理原始指针来避免。例如,与unique_ptr类似的编码错误将如下所示:

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

这将产生编译时错误,因为unique_ptrs构造函数是显式的

使用容器,也许std ::参考。

或者,你可以避免使用new [],并使用std :: vector< Derived&gt ;.然后,你会强制自己设计一个不同的解决方案来发送这个数组到只有Base意识的框架代码。可能,一个模板函数。

void my_framework_code (Base &object) {
    //...
}

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

或者,通过使用std :: reference_wrapper< Base&gt ;.

std::vector<Derived> v(42);
std::vector<std::reference_wrapper<Base>> myArray(v.begin(), v.end());
翻译自:https://stackoverflow.com/questions/37051199/should-this-be-called-some-special-case-of-object-slicing

转载注明原文:c++ 这应该被称为对象切片的一些特殊情况吗?