4

この回答に触発されて、読み取り専用メンバー変数に次のソリューションを使用しています。

template <class T, class OWNER>
class readonly
{
    friend OWNER;

public:
    explicit readonly(const T &t) : m_t(t)
    {
    }

    ~readonly()
    {
    }

    operator const T&() const
    {
        return m_t;
    }

private:
    T& operator =(const T &t)
    {
        m_t = t; 
        return m_t;
    }

    T m_t;
};

これはうまく機能します。パフォーマンスを少し最適化するために、次のように使用します。

class A
{
public:
    A()
    {
    }

    ~A()
    {
    }

#ifdef _DEBUG     // DON'T USE THIS SWITCH, SEE ANSWERS BELOW!
    readonly<int, A> m_x, m_y;
#else
    int m_x, m_y;
#endif
};

ただし、デバッグ ビルドまたはリリース ビルドを実行しているかどうかをチェックするプリコンパイラ スイッチを削除したいと考えています。

編集: ループでパフォーマンスを確認しました。VS2010 を使用すると、約 15 ~ 20% のオーバーヘッドが発生します。自動インライン展開が有効な同じコードにはなりません。

編集 #2: 単体テストを作成し、他のすべてのものを削除しました。もうパフォーマンスの低下はありません。とても素晴らしいです。結局、問題はありませんでした。助けてくれてありがとう!そして、コンストラクターを修正しました。良い呼び出しです。

4

7 に答える 7

5

最適化は役に立たず、まったく同じコードになります。すべてreadonlyが取るに足らないものであり、インライン化されるため、raw Tを使用する場合のオーバーヘッドがなくなります。したがって、解決策は、存在しない問題を修正せず、readonly<int, A>デバッグビルドであるかどうかに関係なく使用することです。

@MooingDuckが指摘したように、initリストを使用するようにコンストラクターを変更する必要があります(おそらくそれも明示的にします)。

于 2012-05-24T18:56:13.030 に答える
3

ヘルパーメタ関数を使用します。

template< typename T, typename Owner >
struct make_read_only
{
#ifdef _DEBUG
    typedef readonly< T, Owner > type;
#else
    typedef T type;
#endif
};

メンバー宣言を次のように変更します。

make_read_only< int, A >::type;
于 2012-05-24T18:56:03.563 に答える
2

あなたのアプローチは、私にとって大きな問題であることに苦しんでいます.DEBUGモードとRELEASEモードで異なるコードを生成する可能性があります. ここで私が考えているのはパフォーマンスではなく、セマンティクスです。オプティマイザが同等のバイナリを生成できないとしたら、私は驚くでしょう。

DEBUG バージョンでは、要素が使用されるたびにユーザー定義の変換が必要ですが、RELEASE ではその変換が削除されるため、別のユーザー定義の変換を使用できるようになり、メンバー属性が変更されたときに別のオーバーロードが選択される可能性があります。関数に引数として渡されます。

一般的なケースではないかもしれませんが、ヒットした場合、アプリケーションが RELEASE で一貫して失敗する理由を特定しようとして、かなりの量のデバッグの苦痛が生じますが、DEBUG バージョンでデバッグすることはできません...

于 2012-05-24T19:26:37.887 に答える
1

const 修飾子にはパフォーマンスの側面はありません。適切なオプティマイザがあれば、デバッグ バージョンとリリース バージョンのボットは同じコードになります。

于 2012-05-24T18:56:45.560 に答える
0

ここでは、少し異なる見方をします。読み取り専用変数が必要であるが、クライアントが変数にアクセスする方法を変更する必要がない場合は、次のテンプレート クラスを試してください。

template<typename MemberOfWhichClass, typename primative>                                       
class ReadOnly {
    friend MemberOfWhichClass;
public:
    inline operator primative() const                 { return x; }

    template<typename number> inline bool   operator==(const number& y) const { return x == y; } 
    template<typename number> inline number operator+ (const number& y) const { return x + y; } 
    template<typename number> inline number operator- (const number& y) const { return x - y; } 
    template<typename number> inline number operator* (const number& y) const { return x * y; }  
    template<typename number> inline number operator/ (const number& y) const { return x / y; } 
    template<typename number> inline number operator<<(const number& y) const { return x <<y; }
    template<typename number> inline number operator>>(const number& y) const { return x >> y; }
    template<typename number> inline number operator^ (const number& y) const { return x ^ y; }
    template<typename number> inline number operator| (const number& y) const { return x | y; }
    template<typename number> inline number operator& (const number& y) const { return x & y; }
    template<typename number> inline number operator&&(const number& y) const { return x &&y; }
    template<typename number> inline number operator||(const number& y) const { return x ||y; }
    template<typename number> inline number operator~() const                 { return ~x; }

protected:
    template<typename number> inline number operator= (const number& y) { return x = y; }       
    template<typename number> inline number operator+=(const number& y) { return x += y; }      
    template<typename number> inline number operator-=(const number& y) { return x -= y; }      
    template<typename number> inline number operator*=(const number& y) { return x *= y; }      
    template<typename number> inline number operator/=(const number& y) { return x /= y; }      
    template<typename number> inline number operator&=(const number& y) { return x &= y; }
    template<typename number> inline number operator|=(const number& y) { return x |= y; }
    primative x;                                                                                
};      

使用例:

class Foo {
public:
    ReadOnly<Foo, int> x;
};

これで Foo.x にアクセスできますが、Foo.x を変更することはできません! ビット演算子と単項演算子も追加する必要があることに注意してください。これは、開始するための単なる例です

于 2014-04-01T01:10:39.630 に答える
-2

100% 確実ではありませんが、テンプレートではできないようです。テンプレートにはプリプロセッサ変数を読み取る手段がないためです。コードを読みやすくするために、READONLY_INT のようなマクロを定義し、他の .h ファイル内で宣言することができます。

于 2012-05-24T18:58:27.183 に答える