简体   繁体   中英

Dynamically changing array size in C++

I need to transform an array from {4, 2 ,5} to {4, 2, 5, 4, 2, 5} . Here's my output: {4, 2, 5, 3.21143e-322, 0, 2} , which is obviously incorrect. But I cannot seem to figure out the issue in my logic. Perhaps another perspective can find that issue.


This is my code:

void repeatArray(double* oldArray, int size) {
    int newSize = size * 2;
    double* newArray = new double[newSize];
    for (int i = 0; i < size; i++) {
        newArray[i] = oldArray[i];
    }
    for (int i = 0; i < size; i++) {
        newArray[size+i] = oldArray[i];
    }
    oldArray = newArray;
    delete [] newArray;
}

int main() {
    double* oldArray = new double[3];
    oldArray[0] = 4;
    oldArray[1] = 2;
    oldArray[2] = 5;
    repeatArray(oldArray, 3);
    for (int i=0; i<6; i++)
        cout << oldArray[i] << endl;
    delete []oldArray;
    return 0;
}

The problem is that merely assigning the new array to the pointer in repeatArray() does not change it from the outside.

What you can do in repeatArray() is to return the newly created array.

double* repeatArray(double* oldArray, int size) {
    int newSize = size * 2;
    double* newArray = new double[newSize];
    for (int i = 0; i < size; i++) {
        newArray[i] = oldArray[i];
    }
    for (int i = 0; i < size; i++) {
        newArray[size+i] = oldArray[i];
    }
    delete [] oldArray;
    return newArray;
}

And in main() :

oldArray = repeatArray(oldArray, 3);


A probably better approach would be to use std::vector that is resized automatically as needed.

The problem is that repeatArray parameters are local to the function, so if you change their value, the change won't be seen past the function call. You can use a pointer to pointer double** oldArray to change what oldArray is pointing to, or return the pointer of the new array location.

However, this is C++ , where you can use STL containers. Your code would become much more simple and readable.

void repeat( std::vector<double>& numbers ) {
   // Reserve rellocates the vector if there is not enough space
   // otherwise, the iterators first and last could be invalidated.
   numbers.reserve( numbers.size() * 2 );

   auto first = numbers.begin();
   auto last = numbers.end();
   std::copy( first, last, std::back_inserter(numbers) );
}

int main() {
   std::vector<double> nums({4, 2, 5});
   repeat(nums);
   for( double num : nums ) {
      std::cout << num << '\n';
   }
   return 0;
}

std::vector takes care of your allocation, reallocation and copy of the elements, and the deallocation of the resources it makes use.

Since you said C++ , I suggest you use a proper container, eg std::vector .

If you don't have a very good reason to do your own memory management, than you should avoid using new and delete , see here for an elaborated explanation.

Using templates enhances the possibility to reuse the repeat function with other types than double .

Thus, your code is reduced to the following and is easier to read.

#include <vector>
#include <iostream>
template <typename T>
std::vector<T> repeat(const std::vector<T>& originalVec) {
    auto repeatedVec = originalVec;
    repeatedVec.insert(repeatedVec.end(), originalVec.begin(), originalVec.end());

    return repeatedVec;
}

int main() {
    std::vector<double> oldArray {4,2,5};

    const auto newArray = repeat(oldArray);

    for (const auto item : newArray) {
        std::cout << item << std::endl;
    }

    return 0;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM