3

クロス プラットフォーム (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 の移動セマンティクス革命は、この非効率性を解決するために何かをしましたか? これを改善できますか?

4

4 に答える 4

6

ラパン、あなたのコードは素晴らしいC++11コードです。C ++ 98/03では、コンパイラの最適化によりコードはおそらく効率的ですが、これらの最適化は保証されていません。C ++ 11では、これらの同じ最適化により、おそらくリターンが無料になりますが、そうでない場合に備えて、文字列はコピーされるのではなく移動されます。

だから、罪悪感のない価値で戻ってきてください!:-)

マイナーニット:

ブロックの先頭ではなく、最初の使用時に値を宣言することをお勧めします。

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

またはおそらく:

return ss.str();

しかし、これはほんの小さな問題です。あなたのコードは素晴らしく効率的です

于 2012-06-30T01:12:32.793 に答える
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(); }
};
于 2012-06-30T08:35:02.587 に答える
-1

RVO / NRVOのない世界では、これにより、C++11より前の標準ライブラリでのコピーの構築を回避する必要があります。文字列用のmoveコンストラクターを備えたポストC++11ライブラリでは、moveコンストラクターが呼び出されることを回避します。それはおそらく些細な違いですが、それでも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;
}
于 2012-06-29T23:51:48.997 に答える
-1

わかりました、これはスレッドセーフではないことを知っています.

const char * myfunc(){

  static std::string mystr;

  /*populate mystr */

  return mystr.c_str();
}

これは、ポインターにしがみつくほど愚かな人は誰もいないことがわかっている場合にのみ機能します。

これは、何があっても漏れない一時的な方法です。

于 2012-06-30T01:16:01.687 に答える