Как правильно передать в метод массив и получить обратно массив другого размера?

Надо передать в метод массив, там он обрабатывается и вернуть результат в виде массива другого размера.
Понимаю, что надо перед вызовом создавать указатель, привязывать к нему массив через new, передавать в метод, там после обработки удалять через delete [] привязанные данные и создавать новые через new.

Запутался в * и & ))

Упрощённо:
Метод(float *arr) {
  ... использование данных
  delete [] arr;
  float *newArr;
  newArr = new float[newSize];
  ... заполнение новыми данными
  arr = &newArr;
}

float *a;
a = new float[size];
Метод(a);
  • Вопрос задан
  • 178 просмотров
Пригласить эксперта
Ответы на вопрос 3
@MarkusD Куратор тега C++
все время мелю чепуху :)
Тебе не нужны new и сырые указатели. Тебе нужен линейный контейнер с хранением элементов в непрерывном блоке памяти. Это будет или std::vector, или std::array.

Для начала можно остановиться на векторе. Еще одним важным типом будет std::span[?] или gsl::span[?][S] если ты не можешь пользоваться C++20.

При реализации твоей функции нужно понять, зачем в твою функцию добавлять управление памятью. В общих случаях, если разработчик начинает управлять памятью в вычислительной функции, это говорит о плохо продуманном алгоритме функции. В редких случаях управление памятью может быть технически обосновано. Твой случай не из таких. В нем незачем управлять памятью, это пользы не сделает, а приведет лишь к переусложнению реализации.

Вот объвление твоей функции: gsl::span<float> Метод( gsl::span<float> values ).
span - это не владеющий памятью тип, обозначающий участок непрерывной памяти с данными определенного типа. span очень легок и является value type - т.е. создан чтобы его передача по значению не приводила к ощутимым нагрузкам. span конструируется из std::vector, std::array, плоских массивов, std::unique_ptr<[]> и сырых блоков памяти.

В своей функции тебе стоит работать с памятью values, считая попутно, сколько элементов ты обработал. А для возврата обработанного участка данных тебе будет достаточно вызвать subspan.

Псевдокод
std::span<float> Метод( std::span<float> values )
{
	size_t processed_count = 0;
	for( float& element : values )
	{
		// ... обработка значений
		// ... изменение processed_count
		// ... условия обрыва цикла
	}
	
	return values.subspan( 0, processed_count );
}

int main()
{
	std::vector<float> values{ 7.83f, 14.1f, 20.3f };
	std::span<float> processed_values = Метод( values );
	
	for( const float& value : processed_values )
	{
		std::cout << value << ' ';
	}
	
	return 0;
}
Ответ написан
Если стандартная библиотека C++ отсутствует у данного, гм, ограниченного компилятора, предлагаю вручную написать аналог std::vector. Для простого хранения чисел хватит за глаза.

template <typename T>
class Vector {
    T* data_;
    size_t size_;

public:
    // 0. техническая часть
    ~Vector() { delete[] data_; }
    Vector(const Vector&) = delete;
    Vector& operator=(const Vector&) = delete;
    Vector(Vector&& o) noexcept : data_(o.data), size_(o.size) {
        o.data_ = nullptr;
        o.size_ = 0;
    }
    Vector& operator=(Vector&& o) noexcept {
        if (&o != this) {
            delete[] data_;
            data_ = o.data_;
            size_ = o.size_;
            o.data_ = nullptr;
            o.size_ = 0;
        }
        return *this;
    }

    // 1. можно создать пустой или заданного размера
    Vector() : data_(nullptr), size(0) {}
    explicit Vector(size_t size) : data_(new T[size]), size_(size) {}

    // 2. можно индексировать
    T& operator[](size_t ind) { return data_[ind]; }
    const T& operator[](size_t ind) const { return data_[ind]; }

    // 3. можно узнать размер... всё!
    size_t size() const { return size_; }
};

// семантика перемещения, если знаешь, что это
template <typename T>
Vector<T>&& move(Vector<T>& vec) {
    return static_cast<Vector<T>&&>(vec);
}

template <typename T>
void fill(Vector<T>& vec, T value) {
    // упражнение для читателя
}

// явное копирование
template <typename T>
Vector<T> copy(const Vector<T>& vec) {
    // упражнение для читателя
}

// арифметика
template <typename T>
Vector<T>& operator+=(Vector<T>& lhs, const Vector<T>& rhs) {
    // упражнение для читателя
}
Ответ написан
@K0lya28
Первый вариант
1) Вам нужно передать указатель по ссылке, чтобы изменить его значение при выделении памяти с помощью new[]
Метод(float& *arr) {}

2) Вы должны изменить указатель a (из main) по ссылке arr
arr = newArr;

Код:
void foo(float& *arr) {
 // ... использование данных
  delete [] arr;
  float *newArr = new float[newSize];
  //... заполнение новыми данными
  arr = newArr;
}

float *a = new float[size];
foo(a);


Второй вариант
Вернуть из функции новый указатель
float* foo(float *arr) {
 // ... использование данных
  delete [] arr;
  float *newArr = new float[newSize];
//... заполнение новыми данными
  return newArr;
}

float *a = new float[size];
a = foo(a);
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы