Я работаю над кодом, в котором массив передается функции путем передачи указателя на первое место. В функции используется часть массива. Это создает небезопасную ситуацию, потому что есть вероятность, что если функция вызывающей стороны не угадывает максимальный размер массива, то функция вызываемой может записать после размера массива и может произойти переполнение стека. Я думал о решении этой проблемы и думал об использовании шаблона функции и передаче массива в качестве ссылки, как показано в этом примере.
modifyArray.h
#define MAXSIZE 10
class modifyArray
{
public:
void create();
void unsafeFunction(double*);
template<int N>
void safeFunction(double (&array)[N] );
private:
int computeLength();
};
modifyArray.cpp
#include <iostream>
#include "modifyArray.h"
int modifyArray::computeLength()
{
return 11;
}
void modifyArray::create()
{
double testarray[MAXSIZE];
unsafeFunction(testarray);
safeFunction(testarray);
}
void modifyArray::unsafeFunction(double* array)
{
int operatingSize = computeLength();
for(int i = 0; i < operatingSize; i++) {
array[i] = i*i;
}
}
template<int N>
void modifyArray::safeFunction(double (&array)[N] )
{
int operatingSize = computeLength();
std::cout<< "Max size" << N <<std::endl;
if(operatingSize > N) return; // Return or raise an exception
for(int i = 0; i < operatingSize; i++) {
array[i] = i*i;
}
}
main.cpp
#include "modifyArray.h"
int main(int argc, const char * argv[]) {
modifyArray C;
C.create();
return 0;
}
Я ищу решение, которое является минимально инвазивным для существующего кода. Здесь я просто должен добавить оператор шаблона, изменить аргумент с двойного * на ссылку и вставить оператор if, чтобы проверить размер. Я не хочу делать серьезную переписать. Также я не хочу использовать динамическое размещение, вектор или массив std :: в основном из-за соображений производительности. Это функция низкого уровня в коде численного моделирования, и производительность очень важна. Есть ли лучшее решение? Есть ли ловушка в том, что я делаю?
Если вы действительно хотите работать с необработанными массивами и хотите безопасно изменить все элементы массива без конца, тогда вы можете передать массив по ссылке, а затем использовать диапазон на основе цикла.
tmeplate <typename T, typename Function, std::size_t N>
void do_work(T (&arr)[N], Function f)
{
for (auto & e : arr)
e = f();
}
Вышеуказанное будет применять результат вызова функции к каждому элементу массива и гарантированно останется в границах массива. Вы можете использовать это как
int main()
{
int arr[10];
do_work(arr, []() { static int i = 0; i++; return i * i; });
for (auto e : arr)
std::cout << e << " ";
}
выход:
1 4 9 16 25 36 49 64 81 100
Других решений пока нет …