メインコンテンツ

AUTOSAR C++14 Rule A6-2-2

Expression statements shall not be explicit calls to constructors of temporary objects only

説明

ルール定義

Expression statements shall not be explicit calls to constructors of temporary objects only.

根拠

コンパイラが短期間使用のために作成して削除するオブジェクトは一時オブジェクトです。コンパイラは次のような特定の目的で一時オブジェクトを作成する場合があります。

  • 参照の初期化

  • 関数から返された値の格納

  • 型キャスト

  • Exception handling

一時オブジェクトは、そのオブジェクトの構築を必要とする式が完全に評価されると破棄されます。たとえば、式 sum = a*b+c の評価で、コンパイラは乗算と加算演算の結果を格納するため、2 つの一時オブジェクトを作成します。式が評価された後、両方の一時オブジェクトが破棄されます。これらのスコープは式ステートメントに制限されます。

式がオブジェクト名なしのコンストラクターの明示的な呼び出しである場合、コンパイラはただちに破棄される、一時オブジェクトを作成します。このようなコンストラクターの明示的呼び出しは以下を示す可能性があります。

  • 誤ってオブジェクト名を省略した。

  • この無名変数が宣言ブロックの終わりまでスコープに残ることを想定していた。

lock_guard オブジェクトが作成される次のコード スニペットを考えます。

void foo(){
std::mutex mymutex;
std::mutex mymutex2;
std::lock_guard<std::mutex> lock{mymutex};
std::lock_guard<std::mutex> {mymutex2};
//...
}
最初の宣言では lock という名前の lock_guard オブジェクトが作成されます。オブジェクト lock は、現在のブロックの終わりまで複数スレッドが同時アクセスしないように mymutex を保護します。2 番目の宣言では mymutex2 に対して同様の保護を試みます。この場合、lock_guard オブジェクトには名前が付けられていないので、宣言ステートメントの直後に破棄されます。おそらく誤りにより、mymutex2 は同時実行の問題から保護されない状態になっています。

コンストラクターへの明示的な呼び出しのみの式ステートメントは避けてください。Resource Acquisition Is Initialization (RAII) パターンを実装するには、名前付きオブジェクトを使用します。

Polyspace 実装

Polyspace® は、無名オブジェクトを構築してそれを使用しない式ステートメントにフラグを設定します。宣言式ステートメント内でオブジェクトを使用する場合は、無名一時オブジェクトを構築できます。たとえば、関数の戻り値または代入の右辺で使用される一時オブジェクトはこのルールに準拠しています。

トラブルシューティング

ルール違反が想定されるものの、Polyspace から報告されない場合は、コーディング規約違反が想定どおりに表示されない理由の診断を参照してください。

すべて展開する

次のコードは、コンストラクターの明示的呼び出しのみのステートメントに、Polyspace がどのようにフラグを設定するかを示します。

#include <cstdint>
#include <fstream>
#include <string>
class MyException {
	MyException(const std::string &);
};
void with_exception() {
	MyException("Exception");              //Noncompliant
	throw MyException("Exception");        //Compliant 
	
};  

Polyspace は、無名一時オブジェクトを構築してそれを使用しない式ステートメントにフラグを設定します。ステートメントで一時オブジェクトを使用する場合、そのステートメントはルールに準拠しています。たとえば、ステートメント MyException("Exception"); にはフラグが設定されます。コンストラクター MyException() の明示的呼び出しによって作成された無名オブジェクトがステートメントで使用されていないためです。ステートメント throw MyException("Exception"); にフラグは設定されません。無名オブジェクトが throw の引数として使用されているためです。

コンパイラは、無名 lock_guard オブジェクトを宣言ステートメントの直後に破棄します。無名 lock_guard オブジェクトは mutex オブジェクトを同時実行の問題から保護できません。Polyspace は、無名 lock_guard オブジェクトの宣言時にステートメントにフラグを設定します。次のコードについて考えます。

#include <cstdint>
#include <mutex>
class A {
public:
	void SetValue1(std::int32_t value) {
		std::lock_guard<std::mutex> {mutex1}; //Noncompliant
		private_value = value;
	}

	void SetValue2(std::int32_t value) {
		std::lock_guard<std::mutex> lock{mutex2}; //Compliant
		private_value = value;
	}
private:
	mutable std::mutex mutex1;
	mutable std::mutex mutex2;
	std::int32_t private_value;
};

  • ステートメント std::lock_guard<std::mutex> {mutex1}; は無名 lock_guard オブジェクトを宣言しています。Polyspace はこのステートメントにフラグを設定します。

  • ステートメント std::lock_guard<std::mutex> lock{mutex2}; にはフラグは設定されません。これは、lock_guard オブジェクトに名前が付けられているためです。

チェック情報

グループ: ステートメント
カテゴリ: Required、Automated