3

私が使用する必要があるフレームワークは、デバッグの補助としてミューテックス所有者の名前を格納できる単純なミューテックス クラスを定義します。

class mutex
{
public:
    explicit mutex(const std::string& mutex_owner = "");

    bool acquire() const;
    bool release() const;

    const std::string& get_name() const {return owner_name_;}

    // ...

private:
    std::string owner_name_;

    // ...
};

ロックが必要ない場合は、パフォーマンス上の理由からこれを渡すことができるように、mutex 型をテンプレート パラメーターにするいくつかのアルゴリズムを変更しました。

class non_mutex
{
public:
    explicit non_mutex(const std::string& mutex_owner = "")     {}

    bool acquire() const               {return true;}
    bool release() const               {return true;}

    std::string get_name() const {return "";}
};

これは名前を格納しないため (これをデバッグする必要はありません)、メンバー関数を .ではなく.get_name()を返すように変更しました。std::stringconst std::string&

ここで私の質問は次のとおりですコードは問題なくコンパイルされ、問題なく動作するように見えますが、このコードベースにはほとんどテストがなく、この関数は通常ではなく、何か問題が発生した場合にのみ使用されます。

この変更によってランタイム エラーが発生する可能性があるのはどのような場合ですか?

これは C++03 環境ですが、C++11 の回答にも興味があります。

4

4 に答える 4

4

値で返されるものは潜在的に悪い割り当てをスローする可能性があり、参照のものはスローされません。したがって、これは問題になる可能性があります。

また、彼らが異なるオーバーロードを呼び出す可能性があり、特性は異なる方法で専門化されますが、私はこれについて心配しません。

于 2012-11-12T10:33:49.697 に答える
1

さて、あなたはもはや定数を返していません。あなたは一時的なものを返しています。

理論的には、これによりユーザーが戻り値を誤用できる可能性がありますか? 多分?

ところで。私はこのように問題を解決します:

static std::string empty_string;
const std::string& get_name() const { return empty_string; }
于 2012-11-12T10:29:47.927 に答える
1

サイレント ブレークの場合、1 つの違いは、返されたオブジェクトまたは return によって参照されたオブジェクトの有効期間です。たとえば、次のコードを考えてみましょう。

const string &stupid_user(const string &s) { return s; }

const string &name = stupid_user(mtx.get_name());
mtx.acquire();
std::cout << name;

ここで、mtxhas typeの場合mutex、これはミューテックスの現在の所有者の名前を . の後に出力しacquireます。mtx型がある場合non_mutex、未定義の動作になります (この場合、const 参照は一時オブジェクトの寿命を延ばしません)。未定義の動作により、明らかにテストに合格する可能性があります。

それほど愚かでないユーザーの場合:

const string &name = mtx.get_name();
mtx.acquire();
std::cout << name;

現在の動作mutexは、新しい所有者をnon_mutex出力し、古い所有者を出力することです。テストがそれをキャッチするかもしれませんし、キャッチしないかもしれませんが、呼び出しコードが一方を想定していて、それが他方である型を指定した場合、呼び出しコードを黙って壊したことになります。

またはどうですか:

auto &&name = mtx.get_name();
mtx.acquire();
std::cout << name;

これは愚かでないユーザーと同じように振る舞うと思いますが、よくわかりません。

あなた(またはこの質問への将来の訪問者)がノイズの多い破損に興味がある場合は、ミューテックスの概念を使用するために許可された式をどのように定義したかによって異なります(提示する2つのクラスが両方とも満たすことを望んでいます)。

たとえば、式&mtx.get_name()が許可されている場合non_mutex、概念の要件を満たしていません。

その式を許可しなかった場合はnon_mutex、要件を満たしている可能性があります。 への呼び出しを含む許可されている式をよく見てくださいget_name。戻り値が「変換可能string」またはそのようなものであることが必要な場合は、問題ありません。

許可された式に関してテンプレート パラメーターの要件を定義しなかった場合、代わりにメンバー関数のシグネチャと戻り値の型に関して定義した場合、(a) 間違いを犯しました。それはテンプレート ベースのコンパイル方法ではありません。 -time ポリモーフィズムが機能するはずであり、(b)non_mutex同じメンバー関数のシグネチャと戻り値の型がありません。

于 2012-11-12T11:09:13.480 に答える
0

あなたの変更に問題はないと思います。どちらもget_name()変更不可能な左辺値を返します。それらを変更しようとすると、C++03 でコンパイラ エラーが発生します。

知識を深めたい場合は、コードをテンプレート化しているため、いつでも SFINAE に基づいて選択できます。これで完全に除去できますnon_mutex::get_name()

于 2012-11-12T11:09:27.570 に答える