#include <iostream>
#include <vector>

using namespace std;

// можно vector<int> - но это будет медленно
// копирование больших объектов медленный процесс
vector<int> ComputeSquares(const vector<int>& data) {
    vector<int> result;
    for (int i = 0; i < data.size(); ++i) {
        result.push_back(data[i] * data[i]);
    }
    return result;
}

void ComputeSquaresInPlace(vector<int>& data) {
    for (int i = 0; i < data.size(); ++i) {
        data[i] *= data[i];
    }
}

// можно передавать и указатель
void ComputeSquaresInPlacePtr(vector<int>* data) {
    for (int i = 0; i < data->size(); ++i) {
        (*data)[i] *= (*data)[i];
    }
}

// можно const int& a - но это будет медленнее работать
// тривиальные типы дешево копировать как есть
int GCD(int a, int b) {
    if (b == 0) {
        return a;
    }
    return GCD(b, a % b);
}

int main() {
    vector<int> data = {1, 6, 2, -5, 3, 10};
    vector<int> result = ComputeSquares(data);
    ComputeSquaresInPlace(data);
    ComputeSquaresInPlacePtr(&data);  // например, в C++ стайлгайде Google (вы можете найти его в интернете) рекомендовано
                                      // изменяемые параметры передавать именно с помощью указателей
                                      // тогда в момент вызова видно, что data будет изменено:
                                      // сравните: DoSmthComplex(a, b, c) и DoSmthComplex(a, b, &c);  - в первом варианте не понятно,
                                      // что изменится, а что нет, а во втором же видно, что c изменится, а a и b останутся как есть

                                      // какой вариант использовать - на ваше усмотрение

    // data будет содержать четвертую степень, а result - квадраты
    for (int i = 0; i < result.size(); ++i) {
        cout << data[i] << " " << result[i] << "\n";
    }

    return 0;
}
