Code
#include "stdafx.h"
#include <iostream>
void someFunc(double* pDoubleArray, int length)
{
double* pNewDoubleArray = new double[length];
for(int i = 0; i < length; i++)
{
pNewDoubleArray[i] = i * 3 + 2;
}
pDoubleArray = pNewDoubleArray;
}
int main()
{
double dbls[] = { 1, 2, 3, 4, 5 };
int length = sizeof dbls / sizeof dbls[0];
std::cout << "Before..." << std::endl;
for(int i = 0; i < length; i++)
{
std::cout << dbls[i] << ", ";
}
std::cout << std::endl;
someFunc(dbls, length);
std::cout << "After..." << std::endl;
for(int i = 0; i < length; i++)
{
std::cout << dbls[i] << ", ";
}
std::cout << std::endl;
while(true){ }
return 0;
}
Output
Before...
1, 2, 3, 4, 5,
After...
1, 2, 3, 4, 5,
Here's what I am trying to do:
1. Create an array and fill it with some values
2. Pass that array as a pointer to a function that will create a new array and reassign the one that was passed in to the newly created array
3. Print out the changes
I am not seeing any changes though, and I do not know why.
The interface of your function someFunc is wrong. It should require the reference of a pointer's address (or the pointer to a pointer) so that you can return the address of your new array. Otherwise, you are simply modifying a local value.
void someFunc(double*& pDoubleArray, int length)
{
double* pNewDoubleArray = new double[length];
for(int i = 0; i < length; i++)
{
pNewDoubleArray[i] = i * 3 + 2;
}
pDoubleArray = pNewDoubleArray;
}
Your calling main function should then pass a value which can be modified:
int main()
{
double dbls[] = { 1, 2, 3, 4, 5 };
double* pArray = dbls;
// ...
someFunc(pArray, length);
// ...
for(int i = 0; i < length; i++)
{
std::cout << pArray[i] << ", ";
}
// ...
}
Ignoring the memory leak issue that results:
void someFunc(double* & pDoubleArray, int length)
// pass by reference ^^^ the pointer
The line pDoubleArray = pNewDoubleArray; assigns the local copy of the pointer
Either pass the pointer by reference, pass a pointer to it, or return the new value
My preference would be to return the new value, bit that's a style issue.
It is unclear why you are passing the old array to a function which does not use it.
If you are changing individual values, then there is no point in creating a new array instance. If not, then simply create a new array and return it.
So, either change the original array:
void someFunc(double* pDoubleArray, int length)
{
for(int i = 0; i < length; i++)
{
pDoubleArray[i] = i * 3 + 2;
}
}
Or return the new array from the function:
// this indicates that the returned value is
// actually a new instance
double* getNewArray(double* pDoubleArray, int length)
{
double* pNewDoubleArray = new double[length];
for(int i = 0; i < length; i++)
{
pNewDoubleArray[i] = i * 3 + 2;
}
return pNewDoubleArray;
}
An alternative is to pass the input array by reference, but that complicates releasing unused instances.
[Edit]
To clarify this last case:
void someFunc(double** pDoubleArray, int length)
{
double* pNewDoubleArray = new double[length];
for(int i = 0; i < length; i++)
{
pNewDoubleArray[i] = i * 3 + 2;
}
*pDoubleArray = pNewDoubleArray;
}
void main()
{
double dbls[] = { 1, 2, 3, 4, 5 };
double* pArray = dbls;
// this will change what pArray
// points to
someFunc(&pArray, 5);
return 0;
}
As I've commented before, the latter approach will lead to memory leaks if pArray points to a heap allocated array before calling someFunc.
Related
int* filtrationBiggerValues(int* values, int nrValues, int givenValue) {
int j = 0;
int *new_array=NULL;
new_array = new int[nrValues];
for (int i = 0; i < nrValues; i++)
if (values[i] >= givenValue)
{
new_array[j] = values[i];
j++;
}
return new_array;
}
void main() {
int y[] = { 1,2,100,18,20,94 };
cout<< filtrationBiggerValues(y, 6, 8)<<"\n";
}
I should see the new array with the values bigger than a certain value, but instead I get its address.
That is not how it works. You are returning a pointer from your function not the value. If you want to see the values as output you should iterate on the array and print out each element separately. Also note returning size of your output array from the function for easy iteration.
int* filtrationBiggerValues(int* values, int nrValues, int givenValue, int& outputSize) {
int j = 0;
int *new_array=NULL;
new_array = new int[nrValues];
for (int i = 0; i < nrValues; i++)
if (values[i] >= givenValue)
{
new_array[j] = values[i];
j++;
}
outputSize = j;
return new_array;
}
void main()
{
int y[] = { 1,2,100,18,20,94 };
int outputSize = 0;
int* output = filtrationBiggerValues(y, 6, 8, outputSize);
for(int i=0; i<outputSize; ++i)
{
cout<< output[i] <<"\n";
}
}
Update (If you want to keep signature of the function as it is)
int* filtrationBiggerValues(int* values, int nrValues, int givenValue) {
int j = 0;
int *new_array=NULL;
new_array = new int[nrValues];
for (int i = 0; i < nrValues; i++)
if (values[i] >= givenValue)
{
new_array[j] = values[i];
j++;
}
new_array[j] = 0;
return new_array;
}
void main()
{
int y[] = { 1,2,100,18,20,94 };
int* output = filtrationBiggerValues(y, 6, 8);
for(int i=0; output[i]>0; ++i)
{
cout<< output[i] <<"\n";
}
}
the name of the array is actually a pointer.
if you try this:
int main()
{
int y[] = { 1,2,100,18,20,94 };
cout << y <<endl;
cout<< filtrationBiggerValues(y, 6, 8)<<"\n";
return 0;
}
the output is two address
0x7ffd7ac2bc10
0xfadc30
So much to say:
int* new_array = NULL; C++ uses nullptr. I.e. int* new_array = nullptr;
However, you should inlue the initialization you do next line:
int* new_array = new int[nrValues];
But you just created a new object on the heap, that you don't delete. That is called a memory leak.. Nowadays we use unique pointers to help us there.
std::unique_ptr<int[]> new_array = new int[nrValues];
However, in C++ we have STL containers handle all the C-style array stuff for you. As new_array is a different size then values, you probably want to use std::vector, which has a dynamic size. The STL containers have something called iterators, which can go over the element more efficiently. However, the STL containers don't have default output functions, so you'll have to write your own.
#include<vector>
#include<iostream>
std::vector<int> getBiggerThen(std::vector<int> const& input, int givenValue) {
std::vector<int> output;
for (auto it = input.cbegin(); it != input.cend(); it++) {
if (*it > givenValue) {
output.push_back(*it);
}
}
return output;
}
std::ostream& operator<< (std::ostream& out, std::vector<int> const& vec) {
for (auto const& el : vec) out << el << " ";
return out;
}
int main() {
auto y = std::vector<int>{ 1,2,100,18,20,94 };
std::cout << getBiggerThen(y, 8) << "\n";
}
oh... also important: in C++ main should always return an int.
Finally, what you are doing is required so often, that the STL library has an built-in algorithm for it. Which can reduce everything to
#include<vector>
#include<algorithm>
#include<iostream>
int main() {
auto y = std::vector<int>{ 1,2,100,18,20,94 };
std::vector<int> output{};
int givenValue = 8;
std::copy_if(std::cbegin(y), std::cend(y), std::back_inserter(output),
[givenValue](int val) { return val >= givenValue; });
for (auto const& el : output) std::cout << el << " ";
std::cout << "\n";
}
When is it better to have a function return a pointer to an array, like this:
int * foo(int n) {
int * output = new int[n];
for (int i = 0; i < n; i++) {
output[i] = i;
}
return output;
}
int main() {
int * arr = foo(10);
return 0;
}
vs having the function not return anything but just set values of an array given in the parameters, like this:
void foo(int n, int output[]) {
for (int i = 0; i < n; i++) {
output[i] = i;
}
}
int main() {
int arr[10];
foo(10, arr);
return 0;
}
For example, I have a function that generates prime numbers, and I would like to return them as an array. Should I use the first option and return a pointer to the array, or pass an array into the function and put the values in that?
When sould I return a pointer to an array
When you have a function that creates an array - but there are better ways to do it in C++ than to return a raw pointer to the memory (since those pointers are easy to forget about so you get memory leaks etc). You can for example use the dynamic array-like std::vector:
std::vector<int> foo(size_t n) {
std::vector<int> output(n);
for(size_t i = 0; i < n; ++i)
output[i] = i;
return output;
}
std::vector<int> arr = foo(10);
std::cout << arr.size() << "\n";
std::cout << arr[9] << "\n";
vs setting values in an existing array
When you already have an array that you want to use as input and you want to modify it.
void foo(std::vector<int>& inout) {
for(int& val : inout)
val += 10; // add 10 to every element
}
I am trying to delete any duplicates but not having much success..
void deleatingRepeatingElement (int myArrayLength, int myArray[])
{
for (int i = 1 ; i < myArrayLength; i++){
// start at second index because you don't need to compare the first element to anything, it can't have duplicate that comes first
for (int j = 0; j < i ; j++){
if (myArray[i] == myArray[j]){
myArray[j] = myArray[j + 1];
myArrayLength--;
}
}
}
}
I think there were two main mistakes:
You didn't shift all of the following items when deleting.
You didn't "reset" after deleting.
Here is annotated code that seems to work:
#include <iostream>
/* Remove element at given index from array
* Returns the new array length
* (Note that "int array[]" means exactly the same as "int *array",
* so some people would consider "int *array" better style)
*/
int arrayRemoveAt(int index, int array[], int arrayLength)
{
// Check whether index is in range
if (index < 0 || index >= arrayLength)
return arrayLength;
for (int i = index + 1; i < arrayLength; i++)
{
array[i - 1] = array[i];
}
return arrayLength - 1;
}
/*
* Returns the new length of the array
*/
int deleatingRepeatingElement(int myArrayLength, int myArray[])
{
for (int i = 1; i < myArrayLength; i++)
{
// start at second index because you don't need to compare the first element to anything, it can't have duplicate that comes first
for (int j = 0; j < i; j++)
{
if (myArray[i] == myArray[j])
{
myArrayLength = arrayRemoveAt(i, myArray, myArrayLength);
// After deleting an entry, we must "reset", because now the index i
// might point to another number, which may be a duplicate
// of a number even before the current j.
// The i-- is so that after i++, we will end up with the same i
i--;
break;
}
}
}
// Important: The caller needs this for looping over the array
return myArrayLength;
}
int main(int argc, char **argv)
{
int array[] = {5, 6, 2, 1, 2, 6, 6};
int newSize = deleatingRepeatingElement(7, array);
for (int i = 0; i < newSize; i++)
{
std::cout << array[i] << std::endl;
}
return 0;
}
If you use a static array (such as in my example, as opposed to a dynamic one), you may consider using std::array or a template construction as shown in https://stackoverflow.com/a/31346972/5420386.
Here is the solution to your problem:
#include <iostream>
#include <set>
#define ARRAY_SIZE(array) (sizeof((array))/sizeof((array[0])))
using namespace std;
int *deleteRepeatedElements(int myArray[], int arrayLength) {
set<int> setArray (myArray, myArray+arrayLength);
int setLength = setArray.size();
static int myPointer[4];
int i = 0;
for (set<int>::iterator it = setArray.begin(); it != setArray.end(); ++it) {
myPointer[i] = *it;
i++;
}
return myPointer;
}
int main() {
int myArray[6] = {5, 3, 5, 6, 2, 4};
int arrayLength = ARRAY_SIZE(myArray);
int* myPointer = deleteRepeatedElements(myArray, arrayLength);
int pointerLength = sizeof(myPointer)/sizeof(*myPointer);
for (int* i = &myPointer[0]; *myPointer != 0; i = ++myPointer) {
cout << *i << " ";
}
cout << '\n';
return 0;
}
struct Test1 {
struct Test2 {
DWORD VA1 = 0;
DWORD VA2 = 0;
Test2(DWORD hp):VA1(hp) { }
} *Ppy[5];
Test1() {
for (int i = 0; i < 5; i++)
*(Ppy + i) = new Test2((DWORD)i+2);
}
~Test1() {
for (int i = 0; i < 5; i++)
delete *(Ppy + i);
}
};
void main() {
Test1*Als = new Test1;
for (int i = 0; i < 5; i++)
Als->Ppy[i]->VA2;
// doesn't work-> cout << Als->*(Ppy + i)->VA2 << endl;
delete Als;
}
Hello
How to convert this whole line(if possible) or at least Ppy[i] to
Pointer style/arithmetic : Als->Ppy[i]->VA2
Something like this but it doesn't work : Als->*(Ppy + i)->VA2
Is there a way to make this even more complex (not asm deep)?
Instead of:
Als->Ppy[i]->VA2;
You can write:
(*(Als->Ppy + i))->VA2;
The pointer to the array is Als->Ppy
The pointer to an element of the array is Als->Ppy + i
The value of an element of the array is *(Als->Ppy + i)
The value of an element of the array is itself a pointer, and you need to wrap the above expression in parens before using it to point to an element of the structure.
A memory leak exists in the following function. The trouble I am having is knowing how, when, where, and what to delete. Here is the code:
#include "stdafx.h"
#include <iostream>
void someFunc(double** ppDoubleArray, int length)
{
double* pNewDoubleArray = new double[length];
for(int i = 0; i < length; i++)
{
pNewDoubleArray[i] = 3 * i + 2;
}
*ppDoubleArray = pNewDoubleArray;
}
int main()
{
double dbls[] = { 1, 2, 3, 4, 5 };
double* pArray = dbls;
int length = sizeof dbls / sizeof dbls[0];
std::cout << "Before..." << std::endl;
for(int i = 0; i < length; i++)
{
std::cout << pArray[i] << ", ";
}
std::cout << std::endl;
someFunc(&pArray, length);
std::cout << "After..." << std::endl;
//Expected series is: 2, 5, 8, 11, 14
for(int i = 0; i < length; i++)
{
std::cout << pArray[i] << ", ";
}
std::cout << std::endl;
while(true){ }
return 0;
}
As you can see, I tried what to delete the new array I allocated after I had used it. It actually makes sense that this didn't work, but I am not sure what to do here..
Added delete[] pArray:
#include "stdafx.h"
#include <iostream>
void someFunc(double** ppDoubleArray, int length)
{
double* pNewDoubleArray = new double[length];
for(int i = 0; i < length; i++)
{
pNewDoubleArray[i] = 3 * i + 2;
}
*ppDoubleArray = pNewDoubleArray;
}
int main()
{
double dbls[] = { 1, 2, 3, 4, 5 };
double* pArray = dbls;
int length = sizeof dbls / sizeof dbls[0];
std::cout << "Before..." << std::endl;
for(int i = 0; i < length; i++)
{
std::cout << pArray[i] << ", ";
}
std::cout << std::endl;
someFunc(&pArray, length);
std::cout << "After..." << std::endl;
//Expected series is: 2, 5, 8, 11, 14
for(int i = 0; i < length; i++)
{
std::cout << pArray[i] << ", ";
}
delete[] pArray;
std::cout << std::endl;
while(true){ }
return 0;
}
Does this solve any, if at all memory leaks in this situation?
You are allocating & deleting an array in the function. And you are also returning it.
int main()
{
// This one is allocated on the stack, so it will be deleted when exiting main()
double dbls[] = { 1, 2, 3, 4, 5 };
double* pArray = dbls;
//...
// Your function allocates some memory now pointed at by pArray
someFunc(&pArray, length);
std::cout << "After..." << std::endl;
//Expected series is: 2, 5, 8, 11, 14
for(int i = 0; i < length; i++)
{
std::cout << pArray[i] << ", ";
}
std::cout << std::endl;
while(true){ }
// Your forgot to delete the memory allocated by your function!!! Memory leak!!!
return 0;
}
Here:
*ppDoubleArray = pNewDoubleArray;
delete[] pNewDoubleArray;
You delete the array that you just passed back to the caller. Don't do that delete! It is up to the caller to manage the memory after you pass it back.
Rather than jump through all these hoops, you should consider writing "real" C++ code, using container objects like std::vector which will manage the memory for you.
Did you mean to do this:
void someFunc(double** ppDoubleArray, int length)
{
for(int i = 0; i < length; i++)
{
*ppDoubleArray[i] = 3 * i + 2;
}
}
I don't understand why you'd allocate a new array if your intent is to modify the one passed in.
In someFunc you allocate array, then set pointer passed by the user, to point to it. Upon exiting the function, you delete that array and user ends-up with a pointer to freed memory.
You cannot delete pNewDoubleArray, as you store its address in ppDoubleArray. You have to delete[] pArray, when it is not used anymore or before setting it to another address (when calling someFunc(&pArray, ...) again).