If the arrays are "fixed" at compile time using a constexpr function is also a good idea:
#include <array>
#include <iostream>
//
// Define an add function template
//
// This will provide compile time checking of equal array sizes
// so we have no need to check that condition at runtime (over and over again).
//
// By making it constexpr we can also use this function's results at compile time (See below).
// Also by using std::array you have a good example on how C++ can return
// arrays from functions.
//
// template makes the code reusable for multiple types and array sizes.
//
// typename type_t makes this function usable for all kinds of types so it isn't restricted to ints
// std::size_t N allows for the compiler to generate correct code for positive array sizes
//
// arr1, arr2 :
// Passed as const because the add function should never change the content of those arrays.
// type_t(&arr1)[N] is C++'s way of passing an array of known size
// so you don't have to pass pointers, pointers to pointers and a seperate size parameter
// Another option would be to use std::array<type_t,N>&, but this syntax for passing arrays
// is very useful knowledge.
//
// constexpr means, if you follow some rules you can use this function at compile time
// which means that the compiler will compile this function and then use it too
//
// auto return type means that you let the compiler work out what type you return
// this can help later when refactoring code.
//
template<typename type_t, std::size_t N>
constexpr auto add(const type_t(&arr1)[N], const type_t(&arr2)[N])
{
// You can't return "C" style arrays from functions but you can return objects.
// std::array is a wrapper object for arrays (with almost no overhead)
// the extra {} at the end will initialize all values in the array to default value for type_t (0 for ints)
// (one of the rules for constexpr, everything must be initialized)
std::array<type_t, N> retval{};
// a standard for loop
for (std::size_t n = 0; n < N; ++n) retval[n] = arr1[n] + arr2[n];
// return the array, since we return a std::array<type_t,N> that will also
// become the return type of the function (auto)
return retval;
}
int main()
{
// constexpr initialization allows these arrays to be used at compile time.
constexpr int arr[] = { 1, 2, 3 };
constexpr int arr2[] = { 7, 4, 6 };
// with constexpr ask the compiler to run add at compile time
// (if the rules for constepxr in add do not fully apply then
// the code will still be executed at runtime)
constexpr auto result = add(arr, arr2);
// static_assert, is like assert but then evaluated at compile time.
// if the assert fails then teh code will not compile.
static_assert(result[0] == 8);
static_assert(result[1] == 6);
static_assert(result[2] == 9);
// to show you can use the results at runtime too
bool comma{ false };
// this is a range based for loop
// using range based for loops ensures you never run out of the
// bounds of an array (reduces bugs)
//
// const auto &
// When looping over all the elements of the array
// value will be a const reference to the current element
// visited.
// a reference to avoid copying data (not so important for ints, but important for
// more complex datatypes)
// const because we are only using it, not modifying it.
for (const auto& value : result)
{
if (comma) std::cout << ", ";
std::cout << value;
comma = true;
}
return 0;
}
std::transform(std::cbegin(arr), std::cend(arr), std::cbegin(arr2), std::begin(arr), std::plus<>{});