Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

returning a string from a function

I wanted to write a function that'll be cross platform (win32 & linux), and return a string representation of the datetime [hh:mm:ss dd-mm-yyyy].

Knowing that I just want to use the returned string as a temporary in a stream fashion as below:

std::cout << DateTime() << std::endl;

I considered writing a function with the following prototype

const char* DateTime();

If you return a character array, you must delete it once you're done. But I just want a temporary, I don't want to have to worry about de-allocating the string.

So I've written a function that just returns an std::string:

#include <ctime>
#include <string>
#include <sstream>

std::string DateTime()
{
    using namespace std;

    stringstream ss;
    string sValue;
    time_t t = time(0);
    struct tm * now = localtime(&t);

    ss << now->tm_hour << ":";
    ss << now->tm_min << ":";
    ss << now->tm_sec << " ";
    ss << now->tm_mday + 1 << " ";
    ss << now->tm_mon + 1 << " ";
    ss << now->tm_year + 1900;

    sValue = ss.str();

    return sValue;
}

I realize that I'm returning a copy of the stack variable in DateTime. This is inefficient in that we create the string on the DateTime stack, populate it, then return a copy and destroy the copy on the stack.

Has the c++11 move-semantics revolution done anything to resolve this inefficiency - can I improve upon this?

like image 740
fishfood Avatar asked Dec 10 '25 13:12

fishfood


2 Answers

lapin, your code is fine C++11 code. In C++98/03 your code will probably be efficient due to compiler optimizations, but those optimizations aren't guaranteed. In C++11, those same optimizations will probably still make your return free, but just in case they don't, your string will be moved instead of copied.

So return by value guilt-free! :-)

Minor nit:

It is best practice to declare your values at the point of first use, instead of at the top of a block:

string sValue = ss.str();
return sValue;

Or perhaps even:

return ss.str();

But this is just a minor nit. Your code is fine and efficient.

like image 140
Howard Hinnant Avatar answered Dec 13 '25 01:12

Howard Hinnant


Another way to do this is to make it a function object with a stream inserter, as in:

struct DateTime()
{
    friend std::ostream& operator<<(std::ostream& os, DateTime)
    {
        time_t t = time(0);
        struct tm * now = localtime(&t);

        os << now->tm_hour << ":";
        os << now->tm_min << ":";
        os << now->tm_sec << " ";
        os << now->tm_mday + 1 << " ";
        os << now->tm_mon + 1 << " ";
        os << now->tm_year + 1900;

        return os;
    }

    // Could be converted to a static method,
    //  since DateTime has no internal state
    std::string str() const
    {
        // the following 3 lines can be replaced by
        //  return boost::lexical_cast<std::string>(*this);
        std::ostringstream ss;
        ss << *this;
        return ss.str();
    }

    operator std::string() const
    { return str(); }
};
like image 33
Nevin Avatar answered Dec 13 '25 01:12

Nevin



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!