Design for class which accepts large array in constructor Let's say we have the following class which performs interpolation on irregularly spaced data:

template&lt;class Real&gt;
class interpolator
{
public:
    interpolator(const Real* const x, const Real* const y, size_t length)
    {
        m_x.resize(length);
        m_y.resize(length);
        for (size_t i = 0; i &lt; length; ++i)
        {
             m_x[i] = x[i];
             m_y[i] = y[i];
        }
    }

    Real interpolate_at(Real x)
    {
        // use m_x and m_y to produce an estimate of y(x):
        return something;
    }

private:
    std::vector&lt;Real&gt; m_x;
    std::vector&lt;Real&gt; m_y;
};


This design has a number of things going for it: For one it is easy to use:

std::vector&lt;double&gt; x;
std::vector&lt;double&gt; y;
// Initialize x and y ...
interpolator&lt;double&gt; interp(x.data(), y.data(), y.size());


Since the constructor accepts primitive types, it can also be wrapped in Python with moderate effort (you'd need a shared object and some template instantiations, but let's assume that can be done). You can also let x and y go out of scope and the interpolator will still work.

The tragic flaw is that it performs a huge memcpy, which is slow and not space efficient.

Is there a way to refactor this class such that


It is easy to wrap in Python (std::shared_ptr's in interfaces are a nightmare to wrap . . .)
It doesn't perform a memcpy
The input data can be allowed to go out of scope and the interpolator still work
Don't pass arrays as pointers ...

... for multiple reasons. Your current design


always copies the arrays x, y deeply
can be misused by passing nullptr and trusts the user that length is chosen correctly.


Instead of 

interpolator(const Real* const x, const Real* const y, size_t length) {  /* ... */ }


use

interpolator(std::vector&lt;Real&gt; x, std::vector&lt;Real&gt; y)
: m_x{std::move(x)}
, m_y{std::move(y)}
{ if (m_x.size() != m_y.size()) throw std::logic_error{"NO!"}; }


or if the memory layout doesn't effect the performance too much

interpolate(std::vector&lt;std::array&lt;Real, 2&gt;&gt; xy): m_xy{std::move(xy)} {}


If you want to initialise your data from any range use templates and constrain its type to guard for errors at compile time.

Prefer regular functions for computations

This means, that an implemented function is also a function in the mathematical sense. Same input data produces same output data. I found that this almost always leads to evaluations which do not change an inner state. Thus it smells to me that

Real interpolate_at(Real);


is not

Real interpolate_at(Real) const;