I have two arrays of each size 3 as:
void main() {
double* arr1 = new double[3];
double* arr2 = new double[3];
for(int i = 0; i < 3; i++) {
arr1[i] = 0;
arr2[i] = 0;
}
}
And I have a function that takes a double array as pointer:
void func(double* arr_6D) {
// expected arr size = 6.
// manipulates values of arr
for(int i = 0; i < 6; i++) {
arr_6D[i] = 1;
}
}
I want to pass in arr1 and arr2 together to the function so that their original values are manipulated by the function.
How can I do this?
Below wouldn't work since it's making a copy of the original arrays:
double *arr_merged = new double[6];
arr_merged[0] = arr1[0];
arr_merged[1] = arr1[1];
arr_merged[2] = arr1[2];
arr_merged[3] = arr2[0];
arr_merged[4] = arr2[1];
arr_merged[5] = arr2[2];
func(arr_merged);
you cannot modify the size of an array you create using new double[<size>], to be able to do your merge so to modify the size use std::vector<float>, also offering a lot of additional behaviors
'func(double * arr_6D) is from a library and fixed. I can't change it to for example, func(std::vector &arr_6d)
you can get the underlying array serving as element storage using the operation data()
std::vector<double> arr1 = { ... }
...
std::vector<double> arr2 = { ... }
...
// concatenate arr1 with arr2
arr1.insert( arr1.end(), arr2.begin(), arr2.end() );
...
// call your func with underlying array
func(arr1.data());
warning to take care when manipulating the underlying array
Related
i'm new to c++ and working through the problem of rearranging a sorted array in O(n) time so that first comes the maximum element, then the minimum, then the second max, then the second min, so it goes.
my solution doesn't pass the tests without an auxiliary array result to which I then copy over my values - see below for the initial and the working solutions:
// initial:
void maxMin(int arr[], int size) {
bool switchPointer = true;
int min_ptr = 0;
int max_ptr = size - 1;
for (int i = 0; i < size; i++) {
if (switchPointer) {
arr[i] = arr[max_ptr];
max_ptr--;
} else {
arr[i] = arr[min_ptr];
min_ptr++;
}
switchPointer = !switchPointer;
}
}
// working
void maxMin(int arr[], int size) {
int* result = new int[size];
bool switchPointer = true;
int min_ptr = 0;
int max_ptr = size - 1;
for (int i = 0; i < size; i++) {
if (switchPointer) {
result[i] = arr[max_ptr];
max_ptr--;
} else {
result[i] = arr[min_ptr];
min_ptr++;
}
switchPointer = !switchPointer;
}
for (int j = 0; j < size; j++) {
arr[j] = result[j]; // copying to original array
}
delete [] result;
}
why do we need an auxiliary result array? thank you!
Because if you apply your algorithm "in-place" you will overwrite MIN values of your original array before you could use them. Imagine:
arr = {1, 2, 3, 4, 5}
expected result is {5, 1, 4, 2, 3}
in first iteration you will do arr[0] = arr[4] // arr[0] is equal to 5 now
in second iteration you will do arr[1] = arr[0] // but this is not what you want, because arr[0] was already changed and is not equal to "1" anymore
Usually you use temp variables when you need to read your original source of data and not the modified version. In your case I think the problem arises when you do
arr[i] = arr[max_ptr]; or arr[i] = arr[min_ptr]; in your non working example. In this case you modify the array and you read (arr[max_ptr]) the same overwritten array leading to inconsistencies in your algorithm. Using an auxiliary variable solves the issue since you read the original data but you store it somewhere else.
I try to build a function which deletes the last element of an array. So I need an input array and its dimension, then delete the last term and obtain a new output array. I don't want that. My goal is to somehow make the output array the new input array. In other words, I want to overwrite the input array with the output array.
So if dimension is 4, I don't want to have a 4-dim array in the memory but only 3-dim table after the deletion.
void del (int* ptr_array, int dim) {
int* temp = ptr_array; //Hold the very first address of the input array.
ptr_array = new int[dim - 1]; // Let the address of the input array be
// the address of new output array. Overwritting.
for (int i = 0; i < dim - 1; i++) {
ptr_array = (temp+i); // Will it remember what is temp+1 if I have
// already overwritten the arrays?
ptr_array++;
}
//delete[] ptr_array; - this one is out of the questions - deletes now the input table.
}
Can you tell me what is wrong with this code? - in fact it doesn't change anything
in you function
for (int i = 0; i < dim - 1; i++) {
ptr_array = (temp+i); // Will it remember what is temp+1 if I have
// already overwritten the arrays?
ptr_array++;
}
does nothing, you wanted
for (int i = 0; i < dim - 1; i++) {
ptr_array[i] = temp[i];
}
Note the delete in your comment is invalid because you do not delete the result of a new[] but a pointer inside the allocated array
If the call is like
int * v = ...;
del(v);
// here v is unchanged
probably you wanted to modify v, in that case you can return the new array or to use an input-output variable using a reference
First possibility :
int* del (int* ptr_array, int dim) {
int* new_array = new int[dim - 1];
for (int i = 0; i < dim - 1; i++) {
new_array[i] = ptr_array[i];
}
delete[] ptr_array;
return new_array;
}
with
int * v = ...;
v = del(v);
Second possibility
void del (int*& ptr_array, int dim) {
int* new_array = new int[dim - 1];
for (int i = 0; i < dim - 1; i++) {
new_array[i] = ptr_array[i];
}
delete[] ptr_array;
ptr_array = new_array;
}
with
int * v = ...;
del(v);
// here v is the new array
Warning these codes suppose the input array has at least one element
However the use of an std::vector<int> does all of that for you and is more practical to use
std::vector<int> v;
...
v.resize(v.size() - 1);
or
std::vector<int> v;
...
v.pop_back();
I'm currently using a particular API such that I must use raw pointers, however given the particular arrangement of the pointers I'm not sure how to best go about clearing the memory and avoiding any undefined behaviour in doing so.
double *data1 = new double[rows*columns];
double **data2 = new double*[rows];
data2[0] = data1; // Point to first row
for (int i = 1; i < columns; i++) {
data2[i] = data2[i - 1] + rows;
}
I've attempted something like below, but I don't think it's right.
for(int i = 0; i < rows; i++) {
delete [] data2[i];
}
delete [] data2;
delete [] data1;
Who owns What?
Is the question which will dictate how you delete objects.
What I think you're doing is creating one large array to hold a two-dimensional array of data, and then creating another array to hold pointers to the beginning of each row.
So that's two news and therefore two deletes.
It might be easier to visualise like this:
struct matrix_view
{
int rows, columns;
// this pointer owns a block of doubles
double* entire_buffer = nullptr;
// this pointer owns a block of pointers, but not the memory
// they point to
double** row_pointers = nullptr;
};
matrix_view create_matrix(int rows, int columns)
{
auto result = matrix_view{ rows, columns, nullptr, nullptr };
auto size = rows * columns;
result.entire_buffer = new double [size];
result.row_pointers = new double* [rows];
auto first = result.entire_buffer;
auto last = first + size;
auto dest = result.row_pointers;
while (first != last) {
*dest++ = first;
first += columns;
}
return result;
}
void destroy_matrix(matrix_view m)
{
// always destroy in reverse order
delete [] m.row_pointers;
delete [] m.entire_buffer;
}
I get very frustrating error in following piece of code. Thats my array.
int **tab2 = new int*[3];
I allocate this like it.
for(i = 0; i < 10; i++) {
tab2[i] = new int[3];
tab2[i][0] = 40;
tab2[i][1] = 10;
tab2[i][2] = 100;
}
Then after using it i want to destroy it.
for(i = 0; i < 10; i++) {
delete [] tab2[i];
}
delete [] tab2;
And this causes core dump every single time. I tried many different ways to destroy it and every time get this error. What im making wrong here ?
This
int **tab2 = new int*[3];
does not do what you think it does.
You want an array that will contain TEN (10) pointers, each to an array of THREE ints.
new int*[3] is an array that contain THREE pointers.
What you want is this (live at coliru):
#include <iostream>
int main() {
int **tab2 = new int*[10];
for(int i = 0; i < 10; i++) {
tab2[i] = new int[3];
tab2[i][0] = 40;
tab2[i][1] = 10;
tab2[i][2] = 100;
}
for(int i = 0; i < 10; i++) {
delete [] tab2[i];
}
delete [] tab2;
}
With
int **tab2 = new int*[3];
you allocate an array of pointers of size 3. But than with
for(i = 0; i < 10; i++) {
tab2[i] = new int[3];
//...
}
you access it with up to index 9. That will surely go wrong.
The deletion process looks fine to me. To fix it, you should allocate an array of pointers with size 10instead of 3, e.g.
int **tab2 = new int*[10];
Looks like what you're trying to do is to create an N by M array, where N is known at runtime and M is fixed (in this case, 3).
Why not just do this?
{
std::array<int, 3> defaults = {{ 40, 10, 100 }};
std::vector<std::array<int, 3>> thing(10, defaults);
}
The vector, thing is automatically deallocated when it goes out of scope, and its size can be set at runtime. You still access the structure in the same way:
thing[1][2] = 3
Manual memory management can be easily avoided by using standard containers and smart pointers. Doing so will keep you code cleaner, and have fewer opportunities for dangling pointers and memory leaks.
Ok, so I'm quite new to C++ and I'm sure this question is already answered somewhere, and also is quite simple, but I can't seem to find the answer....
I have a custom array class, which I am using just as an exercise to try and get the hang of how things work which is defined as follows:
Header:
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();
};
}
Implementation:
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;
}
I'm trying to create an array of pointers to integers, a simplified version of this is as follows:
Array array = Array();
for (int i = 0; i < 2; i++) {
int j = i + 1;
array.addObject(&j);
}
Now the problem is that the same pointer is used for j in every iteration. So after the loop:
array[0] == array[1] == array[2];
I'm sure that this is expected behaviour, but it isn't quite what I want to happen, I want an array of different pointers to different ints. If anyone could point me in the right direction here it would be greatly appreciated! :) (I'm clearly misunderstanding how to use pointers!)
P.s. Thanks everyone for your responses. I have accepted the one that solved the problem that I was having!
I'm guessing you mean:
array[i] = &j;
In which case you're storing a pointer to a temporary. On each loop repitition j is allocated in the stack address on the stack, so &j yeilds the same value. Even if you were getting back different addresses your code would cause problems down the line as you're storing a pointer to a temporary.
Also, why use a void* array. If you actually just want 3 unique integers then just do:
std::vector<int> array(3);
It's much more C++'esque and removes all manner of bugs.
First of all this does not allocate an array of pointers to int
void *array = new void*[2];
It allocates an array of pointers to void.
You may not dereference a pointer to void as type void is incomplete type, It has an empty set of values. So this code is invalid
array[i] = *j;
And moreover instead of *j shall be &j Though in this case pointers have invalid values because would point memory that was destroyed because j is a local variable.
The loop is also wrong. Instead of
for (int i = 0; i < 3; i++) {
there should be
for (int i = 0; i < 2; i++) {
What you want is the following
int **array = new int *[2];
for ( int i = 0; i < 2; i++ )
{
int j = i + 1;
array[i] = new int( j );
}
And you can output objects it points to
for ( int i = 0; i < 2; i++ )
{
std::cout << *array[i] << std::endl;
}
To delete the pointers you can use the following code snippet
for ( int i = 0; i < 2; i++ )
{
delete array[i];
}
delete []array;
EDIT: As you changed your original post then I also will append in turn my post.
Instead of
Array array = Array();
for (int i = 0; i < 2; i++) {
int j = i + 1;
array.addObject(&j);
}
there should be
Array array;
for (int i = 0; i < 2; i++) {
int j = i + 1;
array.addObject( new int( j ) );
}
Take into account that either you should define copy/move constructors and assignment operators or define them as deleted.
There are lots of problems with this code.
The declaration void* array = new void*[2] creates an array of 2 pointers-to-pointer-to-void, indexed 0 and 1. You then try to write into elements 0, 1 and 2. This is undefined behaviour
You almost certainly don't want a void pointer to an array of pointer-to-pointer-to-void. If you really want an array of pointer-to-integer, then you want int** array = new int*[2];. Or probably just int *array[2]; unless you really need the array on the heap.
j is the probably in the same place each time through the loop - it will likely be allocated in the same place on the stack - so &j is the same address each time. In any case, j will go out of scope when the loop's finished, and the address(es) will be invalid.
What are you actually trying to do? There may well be a better way.
if you simply do
int *array[10];
your array variable can decay to a pointer to the first element of the list, you can reference the i-th integer pointer just by doing:
int *myPtr = *(array + i);
which is in fact just another way to write the more common form:
int *myPtr = array[i];
void* is not the same as int*. void* represent a void pointer which is a pointer to a specific memory area without any additional interpretation or assuption about the data you are referencing to
There are some problems:
1) void *array = new void*[2]; is wrong because you want an array of pointers: void *array[2];
2)for (int i = 0; i < 3; i++) { : is wrong because your array is from 0 to 1;
3)int j = i + 1; array[i] = *j; j is an automatic variable, and the content is destroyed at each iteration. This is why you got always the same address. And also, to take the address of a variable you need to use &