2013-05-17 3 views
0

Вот что у меня есть:Заполнение массивов в C++ без перевода индексов

int t[MX]; 

Теперь я хотел бы переписать этот код таким образом, чтобы эффективно добавить один элемент в начало этого массива, не имея для перевода всей индексации на 1 в остальной части кода. Решение этой проблемы может быть что-то вроде этого:

int _t[MX+1]; 
int * const t = _t+1; 

Проблема с этим подходом является то, что сейчас что-то вроде этого больше не работает:

memset(t, 0, sizeof t); 

Проблема заключается в том, что sizeof t возвращает 4, вместо MX * 4, как я бы этого хотел.

Одним из возможных решений может быть:

struct 
{ 
    int a; 
    int b[MX]; 
} _t; 
int (&t)[MX] = _t.b; 

Но я нахожу это довольно безвкусный и неудовлетворительным. Итак, мой вопрос: Есть ли лучший способ?

+5

Зачем вам это использовать над 'std :: vector'? – JBL

+0

Я не хочу переписывать ничего, кроме этой небольшой части кода. Я хотел бы сохранить код как можно более простым, а не вводить некоторые тяжелые классы. Во всяком случае, я действительно не понимаю, как это поможет. – toi333

+2

, тогда вы должны отметить его как 'c' - здесь не так много C++. Кстати, как тяжело? Std :: vector? –

ответ

0

Не только второе решение «неэлегантное и неудовлетворительное», но и неопределенное поведение. См. Ответ на this question для получения дополнительной информации по этой теме.

Первое решение позволяет работать с отрицательными индексами, потому что ptr[index] эквивалентно *(ptr + index), поэтому до тех пор, пока результат попадет в массив, вы будете в порядке.

Решение проблемы sizeof может быть выполнено с помощью подхода, принятого разработчиками std::array<T,size_t>: создайте класс шаблонов, который обертывает массив и выполняет перевод индекса внутри его оператора индексирования.

Если это не работает, вы можете вернуться к комбинации ваших первоначальных двух решений, но без неопределенного поведения, например:

#define MX 1000 

typedef int arr_mx[MX]; 

int _t[MX+1]; 
arr_mx &t = *((arr_mx*)(&_t[1])); 

Вот demo of this approach on ideone.

+0

Спасибо за ответ. Мне также пришлось реализовать оператор преобразования в 'int *', чтобы он полностью совместим с существующим кодом. Таким образом, он работает нормально с 'memset', он просто установит все значения на все, в том числе с индексом -1. Проблема в том, что преобразование в 'int *' должно возвращать указатель на элемент -1, иначе 'memset' попытается установить значение первого элемента после последнего, потому что оператор' sizeof', который не является перегружаемым, должен вернуть размер всего объекта. Теперь функции, которые ожидают получить указатель на элемент 0 моего массива, будут получать -1. – toi333

+0

@ toi333 Оператор 'int *' должен возвращать нетранслируемый адрес. Только оператор 'int & []' должен возвращать переведенный. Таким образом, ваш «memset» сможет заполнить буфер нулями без прохождения конца буфера. Функции, требующие переведенного указателя, должны использовать '& t [0]' вместо '(int *) t', чтобы получить переведенный адрес. – dasblinkenlight

+0

Вот как я его реализовал. К сожалению, то, что вы предлагаете в конце, я не могу сделать, потому что для этого потребуется переписать другие части кода. 't' сам по себе должен быть неявным образом закрыт для' int * 'для элемента 0 (индекс 1 в фактическом массиве). – toi333

Смежные вопросы