C / C ++関数パラメーターがポインターの場合の注意事項

関数を書いているときに、パラメータにポインタが付いていることがありますが、このときは注意が必要です。以下は注意事項を説明する例です。


プロトタイプの例

次のように、単純なC ++クラス(Cの原理は似ています)があるとします。

class Test
{
    
    
public:
	Test() 
	{
    
    
		m_ptr = nullptr;
	}

	void setPtr(int *ptr)
	{
    
    
		m_ptr = ptr;
	}

	int *getPtr(void)
	{
    
    
		return m_ptr;
	}
	
private:
	int * m_ptr;
};

このクラスには、2つのメソッドを持つプライベートポインタ変数m_ptrがあります。setPtr()はm_ptrを設定するために使用され、getPtr()はm_ptrを取得するために使用されます。

テストコードは次のとおりです。

int main(void)
{
    
    
    Test test;
	int data = 100;

	test.setPtr(&data);
	int *retPtr = test.getPtr();
	if (retPtr != nullptr)
        std::cout << *retPtr << "\n";
    
    return 0;
}

印刷は次のとおりです。
ここに画像の説明を挿入


エラーが発生しやすい2つの状況

getPtr()の戻り値を使用してポインタが有効かどうかを判断する場合は、次の形式に書き換えることができます。

bool getPtr(int * ptr)
{
    
    
	if (m_ptr == nullptr)
	{
    
    
		return false;
	}
	else
	{
    
    
		ptr = m_ptr;
		return true;
	}
}

テストコードは次のとおりです。

int main(void)
{
    
    
	Test test;
	int data = 100;

	test.setPtr(&data);

	int *retPtr = nullptr;
	if (test.getPtr(retPtr) == true)
	{
    
    
		std::cout << *retPtr << "\n";
	}

	return 0;
}

印刷は空です!これは予想と同じではありません。getPtr()の戻り値はtrueであり、テストのm_ptrがnullptrではないことを示しています。それでは、なぜ正しいポインター値を取得しなかったのでしょうか。

これは、C / C ++関数のパラメーターが値で渡されるためです。以前は、関連する概念を学習するときに、ポインターについての発言がありました。本質は値で渡すことです。retPtrをgetPtr()に渡すと、実際には次のようになります。この文を実行し、

int *ptr = retPtr;

ポインタ変数ptrが再生成され、retPtrの値がptrにコピーされます。ptrに対する後続の操作はretPtrの値に影響を与えないため、正しいポインタ値が取得されません。


3つの解決策

2つの方法があります、

1.セカンダリポインタを使用します

ターゲット変数は第1レベルのポインターであるため、第2レベルのポインターを使用して解決できます。

bool getPtr(int ** pptr)
{
    
    
	if (m_ptr == nullptr)
	{
    
    
		return false;
	}
	else
	{
    
    
		(*pptr) = m_ptr; // key
		return true;
	}
}

コードで最も重要なことは、(*pptr) = m_ptr;間違いを犯しやすいことです。これは、第2レベルのポインターを逆参照してから割り当てることです。記述しないでくださいpptr = &m_ptr;。これは、前の値の受け渡しの問題になり、正しいポインターになります。値を取得できません。

テストコードは次のとおりです。

int main(void)
{
    
    
	Test test;
	int data = 100;

	test.setPtr(&data);

	int *retPtr = nullptr;
	if (test.getPtr(&retPtr) == true) // 要取retPtr的地址传过去
	{
    
    
		std::cout << *retPtr << "\n";
	}

	return 0;
}
2. C ++参照を使用する

第2レベルのポインタは確かに問題を解決できますが、脳は1次元のものを扱うのが好きで、2次元が発生すると失神しやすいため、人を混乱させやすいという欠点があります。

C ++参照を使用すると、次のようにセカンダリポインタの使用を回避できます。

bool getPtr(int *& ptr)
{
    
    
	if (m_ptr == nullptr)
	{
    
    
		return false;
	}
	else
	{
    
    
		ptr = m_ptr;
		return true;
	}
}

それでもパラメータが少し複雑だと感じる場合int*は、次のようにtypedefを使用してエイリアス指定できます。

typedef int *  newType;

bool getPtr(newType& ptr)
{
    
    
	if (m_ptr == nullptr)
	{
    
    
		return false;
	}
	else
	{
    
    
		ptr = m_ptr;
		return true;
	}
}

これにより、理解しやすくなります。

テストコードは次のとおりです。

int main(void)
{
    
    
	Test test;
	int data = 100;

	test.setPtr(&data);

	int *retPtr = nullptr;
	if (test.getPtr(retPtr) == true) 
    {
    
    
		std::cout << *retPtr << "\n";
	}

	return 0;
}

次のように印刷し、[
ここに画像の説明を挿入
OK]を確認します


4つの要約

この記事では、主に関数パラメーターがポインターの場合の注意事項について説明します。ポインターパラメーターを使用して値を取得する場合は、特に注意が必要です。第2レベルのポインターまたはC ++参照を使用して問題を解決できます。

文章に何か問題がありましたら、訂正するためのメッセージを残したいと思います。読んでいただきありがとうございます。

おすすめ

転載: blog.csdn.net/whahu1989/article/details/106033768