我想编写一个跨平台(win32& linux)的函数,并返回日期时间的字符串表示形式[hh:mm:ss dd-mm-yyyy]。
知道我只想以流方式将返回的字符串用作临时字符串,如下所示:
std::cout << DateTime() << std::endl;
我考虑用以下原型编写函数
const char* DateTime();
如果返回字符数组,则必须在完成后将其删除。但我只想要一个临时的,我不想担心取消分配字符串。
所以我编写了一个只返回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;
}
我意识到我正在DateTime中返回堆栈变量的副本。这是低效的,因为我们在DateTime堆栈上创建字符串,填充它,然后返回副本并销毁堆栈上的副本。
c ++ 11移动 - 语义革命是否已经做了任何事情来解决这种低效问题 - 我可以改进吗?
答案 0 :(得分:6)
lapin,你的代码是很好的C ++ 11代码。在C ++ 98/03中,由于编译器优化,您的代码可能可能高效,但不保证这些优化。在C ++ 11中,那些相同的优化可能仍然会使你的返回空闲,但是如果他们不这样做,你的字符串将被移动而不是被复制。
所以按价值回报无罪! : - )
Minor nit:
最佳做法是在首次使用时声明您的值,而不是在块的顶部:
string sValue = ss.str();
return sValue;
或者甚至可能:
return ss.str();
但这只是一个小问题。您的代码很好和效率。
答案 1 :(得分:5)
另一种方法是使用流插入器使其成为函数对象,如:
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(); }
};
答案 2 :(得分:-1)
在没有RVO / NRVO的世界中,这应该避免在C ++ 11之前的标准库中进行复制。在一个带有移动构造函数的C ++ 11库中,它仍然可以避免调用移动构造函数;这可能是一个微小的差异,但OP仍在询问如何做得更好。
(是的,我同意从字符串继承是丑陋但它确实有效。)
#include <ctime>
#include <string>
#include <sstream>
#include <iostream>
using namespace std;
class DateString : public string {
public:
DateString() : string() {
stringstream ss;
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;
append(ss.str());
}
};
int main()
{
cout << DateString() << endl;
return 0;
}
答案 3 :(得分:-1)
好的,我知道这不是线程安全的,所有这些和我可能会被归结为地狱结束,但我在我使用的图书馆中看到了以下内容(CERN& #39; s ROOT):
const char * myfunc(){
static std::string mystr;
/*populate mystr */
return mystr.c_str();
}
这只有在您知道没有人会如此愚蠢以至于坚持指针时才有效。
这是一种临时的方式,无论如何都不会泄漏。