Q:

how to determine C++ function type?

How to decide whether a function should have a type? I mean, should it have a return type? For example,
double add(double a, double b)
{
double sum;
sum = a + b;
return sum;
}

double sum;
void add(double a, double b, double sum)
{
sum = a + b;
}

are these two same?

A:

A function must always have a type, although the return type can
be void.  Generally, however, if the function has a value, it
should use a return value; functions without return values are
usually only used for side effects.  (There might be an
exception for functions with more than one return value, but
such functions should be relatively rare.) 
And finally, C++ uses pass by value, so your second example will
never modify the global sum.  You need to specify pass
by non-const reference:
void add( double a, double b, double& sum )...

or use a pointer.
EDIT:
With regards to the performance implications of returning
a complex type: C++ has been designed to allow a certain number
of optimizations, called RVO (for Return Value Optimization) and
NRVO (for Named Return Value Optimization); C++ has added move
semantics as well.  So performance is rarely a reason to violate
good programming practices (which argue for return values).  If
the profiler does show a problem, however, the best solution is
probably something along the lines of:
void
doConcat( std::vector<double> const& a,
          std::vector<double> const& b,
          std::vector<double>& results )
{
    results.reserve( a.size() + b.size() );
    results = a;
    results.insert( results.end(), a.begin(), a.end() );
}

std::vector<double>
Concat( std::vector<double> const& a, std::vector<double> const& b )
{
    std::vector<double> sum;
    doConcat( a, b, sum ):
    return sum;
}

This way, most of the client code can continue using the natural
interface, and only the places where the profiler insists will
have to use the awkward interface.

