Хорошо, поэтому я довольно новичок в 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 Спасибо всем за ваши ответы. Я принял тот, который решил проблему, которая у меня была!
Прежде всего это не выделяет массив указателей на 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 ) );
}
Учтите, что либо вы должны определить конструкторы копирования/перемещения и операции присваивания, либо определить их как удаленные.
Я предполагаю, что вы имеете в виду:
array[i] = &j;
В этом случае вы сохраняете указатель на временный. На каждом цикле повторение j
выделяется в стеке стека, поэтому &j
yeilds то же значение. Даже если вы возвращаете разные адреса, ваш код может вызвать проблемы в строке, поскольку вы храните указатель на временный.
Кроме того, зачем использовать массив void*
. Если вы на самом деле просто хотите 3 уникальных целых числа, просто выполните:
std::vector<int> array(3);
Это намного больше C++ 'esque и удаляет всевозможные ошибки.
если вы просто
int *array[10];
ваша переменная массива может распадаться на указатель на первый элемент списка, вы можете ссылаться на указатель i-го целого числа:
int *myPtr = *(array + i);
который на самом деле является еще одним способом написать более распространенную форму:
int *myPtr = array[i];
void * не совпадает с int *. void * представляет собой указатель на пустоту, который является указателем на определенную область памяти без какой-либо дополнительной интерпретации или информации о данных, на которые вы ссылаетесь
С этим кодом много проблем.
void* array = new void*[2]
создает массив из 2 указателей на указатель на void, индексированных 0 и 1. Затем вы пытаетесь записать в элементы 0, 1 и 2. Это неопределенное поведениеvoid
на массив указателя на указатель на void. Если вам действительно нужен массив указателя на целое, тогда вы хотите int** array = new int*[2];
, Или, возможно, просто int *array[2];
если вам действительно не нужен массив в куче.j
вероятно, находится в одном и том же месте каждый раз через цикл - он, вероятно, будет размещен в том же месте в стеке - так что &j
- это тот же адрес каждый раз. В любом случае, j
закончится, когда цикл завершится, а адреса (адреса) будут недействительными.Что вы на самом деле пытаетесь сделать? Там может быть лучший способ.
int** array = new int*[2];
Есть некоторые проблемы:
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 - автоматическая переменная, и содержимое уничтожается на каждой итерации. Вот почему у вас всегда был тот же адрес. А также, чтобы принять адрес переменной, вам нужно использовать &
array[i] = *j;
сarray[i] = &j;
void *array = new void*[2];
сint *array = new int*[2];