C ++ указатель на int в циклах?

0

Хорошо, поэтому я довольно новичок в C++, и я уверен, что на этот вопрос уже что-то ответили, а также довольно просто, но я не могу найти ответ....

У меня есть собственный класс массива, который я использую как упражнение, чтобы попытаться понять, как работают вещи, которые определяются следующим образом:

Заголовок:

class Array {
private:
    // Private variables
    unsigned int mCapacity;
    unsigned int mLength;
    void **mData;

public:
    // Public constructor/destructor
    Array(unsigned int initialCapacity = 10);

    // Public methods
    void addObject(void *obj);
    void removeObject(void *obj);
    void *objectAtIndex(unsigned int index);
    void *operator[](unsigned int index);
    int indexOfObject(void *obj);
    unsigned int getSize();
    };
}

Реализация:

GG::Array::Array(unsigned int initialCapacity) : mCapacity(initialCapacity) {
    // Allocate a buffer that is the required size
    mData = new void*[initialCapacity];
    // Set the length to 0
    mLength = 0;
}

void GG::Array::addObject(void *obj) {
    // Check if there is space for the new object on the end of the array
    if (mLength == mCapacity) {
        // There is not enough space so create a large array
        unsigned int newCapacity = mCapacity + 10;
        void **newArray = new void*[newCapacity];
        mCapacity = newCapacity;
        // Copy over the data from the old array
        for (unsigned int i = 0; i < mLength; i++) {
            newArray[i] = mData[i];
        }
        // Delete the old array
        delete[] mData;
        // Set the new array as mData
        mData = newArray;
    }
    // Now insert the object at the end of the array
    mData[mLength] = obj;
    mLength++;
}

void GG::Array::removeObject(void *obj) {
    // Attempt to find the object in the array
    int index = this->indexOfObject(obj);
    if (index >= 0) {
        // Remove the object
        mData[index] = nullptr;
        // Move any object after it down in the array
        for (unsigned int i = index + 1; i < mLength; i++) {
            mData[i - 1] = mData[i];
        }
        // Decrement the length of the array
        mLength--;
    }
}

void *GG::Array::objectAtIndex(unsigned int index) {
    if (index < mLength) return mData[index];
    return nullptr;
}

void *GG::Array::operator[](unsigned int index) {
    return this->objectAtIndex(index);
}

int GG::Array::indexOfObject(void *obj) {
    // Iterate through the array and try to find the object
    for (int i = 0; i < mLength; i++) {
        if (mData[i] == obj) return i;
    }
    return -1;
}

unsigned int GG::Array::getSize() {
    return mLength;
}

Я пытаюсь создать массив указателей на целые числа, упрощенная версия выглядит следующим образом:

Array array = Array();
for (int i = 0; i < 2; i++) {
    int j = i + 1;
    array.addObject(&j);
}

Теперь проблема в том, что один и тот же указатель используется для j на каждой итерации. Итак, после цикла:

array[0] == array[1] == array[2];

Я уверен, что это ожидаемое поведение, но это не совсем то, что я хочу, я хочу, чтобы массив разных указателей имел разные значения. Если бы кто-нибудь мог указать мне в правильном направлении здесь, было бы очень полезно! :) (я явно не понимаю, как использовать указатели!)

Ps Спасибо всем за ваши ответы. Я принял тот, который решил проблему, которая у меня была!

  • 0
    заменить array[i] = *j; с array[i] = &j;
  • 0
    а также заменить void *array = new void*[2]; с int *array = new int*[2];
Показать ещё 10 комментариев
Теги:
arrays
pointers
for-loop

5 ответов

2
Лучший ответ

Прежде всего это не выделяет массив указателей на int

void *array = new void*[2];

Он выделяет массив указателей на void.

Вы не можете разыменовывать указатель на void, поскольку тип void является неполным типом, он имеет пустой набор значений. Таким образом, этот код недействителен

array[i] = *j;

И, кроме того, вместо *j должно быть &j Хотя в этом случае указатели имеют недопустимые значения, потому что будет указывать память, которая была уничтожена, потому что j является локальной переменной.

Петля также неверна. Вместо

for (int i = 0; i < 3; i++) {

там должен быть

for (int i = 0; i < 2; i++) {

Вы хотите следующее:

int **array = new int *[2];

for ( int i = 0; i < 2; i++ ) 
{
   int j = i + 1;
   array[i] = new int( j );
}

И вы можете выводить объекты, на которые указывает

for ( int i = 0; i < 2; i++ ) 
{
   std::cout << *array[i] << std::endl;
}

Чтобы удалить указатели, вы можете использовать следующий фрагмент кода

for ( int i = 0; i < 2; i++ ) 
{
   delete array[i];
}

delete []array;

EDIT: Когда вы изменили свой оригинальный пост, я также добавлю в свою очередь свой пост.

Вместо

Array array = Array();
for (int i = 0; i < 2; i++) {
    int j = i + 1;
    array.addObject(&j);
}

там должен быть

Array array;
for (int i = 0; i < 2; i++) {
    int j = i + 1;
    array.addObject( new int( j ) );
}

Учтите, что либо вы должны определить конструкторы копирования/перемещения и операции присваивания, либо определить их как удаленные.

  • 0
    Ах, спасибо, оооочень много! Ваше редактирование решает мою проблему!
4

Я предполагаю, что вы имеете в виду:

array[i] = &j;

В этом случае вы сохраняете указатель на временный. На каждом цикле повторение j выделяется в стеке стека, поэтому &j yeilds то же значение. Даже если вы возвращаете разные адреса, ваш код может вызвать проблемы в строке, поскольку вы храните указатель на временный.

Кроме того, зачем использовать массив void*. Если вы на самом деле просто хотите 3 уникальных целых числа, просто выполните:

std::vector<int> array(3);

Это намного больше C++ 'esque и удаляет всевозможные ошибки.

  • 0
    Я использую void *, потому что у меня действительно есть класс Array, который используется для хранения указателей на различные типы объектов и пытался использовать один и тот же класс для хранения целых. Я собираюсь обновить мой вопрос с более точным кодом.
1

если вы просто

int *array[10];

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

int *myPtr = *(array + i);

который на самом деле является еще одним способом написать более распространенную форму:

int *myPtr = array[i];

void * не совпадает с int *. void * представляет собой указатель на пустоту, который является указателем на определенную область памяти без какой-либо дополнительной интерпретации или информации о данных, на которые вы ссылаетесь

  • 0
    Массивы не указатели. Распадается на указатель.
  • 0
    stackoverflow.com/questions/3959705/arrays-are-pointers :-)
Показать ещё 5 комментариев
1

С этим кодом много проблем.

  1. Объявление void* array = new void*[2] создает массив из 2 указателей на указатель на void, индексированных 0 и 1. Затем вы пытаетесь записать в элементы 0, 1 и 2. Это неопределенное поведение
  2. Вы почти наверняка не хотите указатель void на массив указателя на указатель на void. Если вам действительно нужен массив указателя на целое, тогда вы хотите int** array = new int*[2]; , Или, возможно, просто int *array[2]; если вам действительно не нужен массив в куче.
  3. j вероятно, находится в одном и том же месте каждый раз через цикл - он, вероятно, будет размещен в том же месте в стеке - так что &j - это тот же адрес каждый раз. В любом случае, j закончится, когда цикл завершится, а адреса (адреса) будут недействительными.

Что вы на самом деле пытаетесь сделать? Там может быть лучший способ.

  • 1
    это должно быть int** array = new int*[2];
  • 0
    Я только что обновил код (я надеюсь) лучше (меньше опечаток).
Показать ещё 1 комментарий
0

Есть некоторые проблемы:

1) void *array = new void*[2]; неверно, потому что вам нужен массив указателей: void *array[2];

2) for (int я = 0; я < 3; i++) {: неверно, потому что ваш массив от 0 до 1;

3) int j = я + 1; array[i] = *j; int j = я + 1; array[i] = *j; j - автоматическая переменная, и содержимое уничтожается на каждой итерации. Вот почему у вас всегда был тот же адрес. А также, чтобы принять адрес переменной, вам нужно использовать &

Ещё вопросы

Сообщество Overcoder
Наверх
Меню