8

例えば:

int StrLen(const std::string &s = "default string") {
  const std::string &t = "another string";  // BTW, is this line safe?
  return s.size();
}

アップデート

SoapBox の結論は正しいですが、その理由は完全には正しくありません。

一時オブジェクトの有効期間は、それを保持する参照と同じになるように自動的に延長されます。

これは通常、いくつかの例外を除いて当てはまります。ひとつはそれ

「関数呼び出しの参照パラメーターへの一時的なバインドは、呼び出しを含む完全な式が完了するまで持続します。」

この例外は、デフォルトの引数のケースに適用されると思います。

別の例外は、SoapBox の回答の追加の例に関連しています。

「関数 return ステートメントの戻り値にバインドされた一時的な有効期間は延長されません。一時的なものは、return ステートメントの完全な式の最後で破棄されます。」

4

3 に答える 3

5

はい、どちらも安全に実行できます。それらは一時オブジェクトを構築し、一時オブジェクトの有効期間は、それを保持する参照と同じになるように自動的に延長されます。

ただし、これは安全ではない一時的なものでよくある間違いです。

std::string const &accessor() const {
    if (my_name_is_valid())
        return m_my_name;
    else
        return "";
}

accessor関数内でテンポラリが作成され、それへの参照が返されるため、これは無効です。呼び出し元は、破壊されたオブジェクトへの参照を受け取ります...これは未定義の動作であり、通常はクラッシュを引き起こします。

于 2012-07-20T01:07:01.497 に答える
3

SoapBox の答えは正しいですが、制限が何であるかが常に明らかであるとは限りません。

これは通常、いくつかの例外を除いて当てはまります。1 つは、「関数呼び出しの参照パラメーターへの一時的なバインドは、呼び出しを含む完全な式が完了するまで持続する」というものです。この例外は、デフォルトの引数の場合に適用されると思います。

時には微妙な方法ではありますが、次の 2 つの例を考慮します。

struct A { A(std::string const& s): _ref(s) {} std::string const& _ref; };

struct B { B(std::string s): _ref(s) {} std::string const& _ref; };

どちらの例でも、関数はコンストラクターです。

  • In A: 完全な式の最後が安全ではないことを意味するまで、一時の有効期間が延長されA a("Hello"); std::cout << a._ref << "\n";ます。一時的なものは最初のものまでしか生きませんでした;
  • In B: パラメータ自体は一時的なものであり、ここではconst-reference へのバインディングはまったくありません。ただし、優れたコンパイラは警告します。

もう 1 つの例外は、SoapBox の回答の追加の例に関連しています。

returnこれは、ステートメントが一般的に機能する方法に由来します。その下に、標準に関する限り進行中の 2 つのコピーがあります。あれは:

  1. 呼び出すreturnと、結果が「結果スロット」にコピーされます
  2. 呼び出し元は、「結果スロット」の値をそのストレージにコピーします (存在する場合)。

もちろん、コピーを最適化して取り除くこともできますが (コピーの省略)、一時的なオブジェクトの有効期間は、バインドされた元のconst-reference までしか延長されないため、これは重要です。その参照のコピーが元の有効期間を超えた場合、それはガベージを参照し、それがreturnステートメントで発生します。

于 2012-07-20T06:57:45.610 に答える
-4

はい。文字列は静的テキストとして割り当てられ、移動または変更されません。

于 2012-07-20T01:06:01.523 に答える