読者です 読者をやめる 読者になる 読者になる

Flat Leon Works

アプリやゲームを作ってます。

【C++ アイデア】関数内でメンバ変数を定義する

メンバ関数の中でメンバ変数の定義ができたら便利だろうなと思ったので、方法を模索してみました。半分ネタです。

やりたいのはこういう感じのことです。

class A
{
    int m_Value; // こっちは普通のメンバ変数
public:
    void Func( void )
    {
        local int m_State = 0; // 関数内でメンバ変数を定義
        if ( m_State == 0 ){ m_State = 1; }
    }
};

マクロとstd::mapを使うことでそれっぽく実装できました。

#include <stdio.h>
#include <map>
 
#define LOCAL_VAR_DECL( type, var_name ) static std::map<void*, type> var_name
#define LOCAL_VAR_INIT( var_name ) if ( var_name.find( this ) == var_name.end() ) var_name[this]
#define LOCAL_VAR_DEF( type, var_name, init ) LOCAL_VAR_DECL( type, var_name ); LOCAL_VAR_INIT( var_name ) = init
#define LOCAL_VAR( var_name ) var_name[this]
 
class A
{
public:
    void Func( void )
    {
        LOCAL_VAR_DEF( int, m_State, 0 ); // 関数内でメンバ変数を定義
       #define m_State LOCAL_VAR( m_State ) // m_State でアクセスできるようdefineしておく
 
        switch( m_State )
        {
            case 0:
            {
                printf( "m_State = 0\n" );
                m_State = 1;
                break;
            }
            case 1:
            {
                printf( "m_State = 1\n" );
                m_State = 0;
                break;
            }
        }
    }
};

https://ideone.com/C1rUV5

std::map<void*,型>でthisポインタをキーにしてアクセスすることで、メンバ変数のようなものを実現しています。std::mapの変数を関数内のstatic変数として定義しているので他の関数からは参照できませんが、関数外でLOCAL_VAR_DEFを使えば他の関数からも利用できると思います。

ところで、この実装は問題点がたくさんあります。

  • インスタンスが破棄されたあとも、動的メンバ変数データが残り続けてしまう。
  • インスタンスが破棄されたあとに、同じアドレスに同じクラスのインスタンスが生成された場合に、前のインスタンスのデータを参照してしまう。
  • アクセスするたびに、mapを検索するので効率が悪い。

このように致命的な問題があるので、実際に動くコードでは使ってはいけません。

ではどこで使うのかというと、以下の様な場面では役に立つかもしれません。

  • デバッグなどで一時的にメンバ変数を追加したい場合
  • メンバ関数の実装中に新しいメンバ変数が欲しくなったときに、とりあえずその場でメンバ変数を定義したい場合(あとで正式にメンバ変数を定義する)

どちらにしてもリリース版には残さないようにしましょう。