Законно ли приводить указатель на ссылку на массив, используя static_cast в C ++?

У меня есть указатель T * pValues что я хотел бы рассматривать как T (&values)[N]

В этом так ответ https://stackoverflow.com/a/2634994/239916, предлагаемый способ сделать это

T (&values)[N] = *static_cast<T(*)[N]>(static_cast<void*>(pValues));

Я беспокоюсь об этом. В его примере pValues инициализируется следующим образом

T theValues[N];
T * pValues = theValues;

Мой вопрос, является ли приведенная конструкция законной, если pValues происходит от любой из следующих конструкций:

1:

T theValues[N + M]; // M > 0
T * pValues = theValues;

2:

T * pValues = new T[N + M]; // M >= 0

16

Решение

Краткий ответ: вы правы. Актерский состав безопасен, только если pValues имеет тип T[N] и оба упомянутых вами случая (другой размер, динамически размещаемый массив), скорее всего, приведут к неопределенное поведение.


Хорошая вещь о static_cast заключается в том, что некоторые дополнительные проверки выполняются во время компиляции, поэтому, если вам кажется, что вы делаете что-то не так, компилятор будет жаловаться на это (по сравнению с уродливым приведением в стиле C, которое позволяет вам делать почти все), например:

struct A { int i; };
struct C { double d; };

int main() {
A a;
// C* c = (C*) &a; // possible to compile, but leads to undefined behavior
C* c = static_cast<C*>(&a);
}

дам тебе: invalid static_cast from type ‘A*’ to type ‘C*’

В этом случае вы приведете к void*что с точки зрения проверок, которые могут быть сделаны во время компиляции, является законным почти для всего, и наоборот: void* может быть возвращено почти ко всему, что делает использование static_cast совершенно бесполезен в первую очередь, так как эти проверки становятся бесполезными.

Для предыдущего примера:

C* c = static_cast<C*>(static_cast<void*>(&a));

не лучше чем:

C* c = (C*) &a;

и, скорее всего, приведет к неправильному использованию этого указателя и неопределенное поведение с этим.


Другими словами:

A arr[N];
A (&ref)[N] = *static_cast<A(*)[N]>(&arr);

это безопасно и просто отлично. Но как только вы начинаете злоупотреблять static_cast<void*> нет никаких гарантий относительно того, что на самом деле произойдет, потому что даже такие вещи, как:

C *pC = new C;
A (&ref2)[N] = *static_cast<A(*)[N]>(static_cast<void*>(&pC));

становится возможным.

9

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]