メインコンテンツ

AUTOSAR C++14 Rule A12-8-1

Move and copy constructors shall move and respectively copy base classes and data members of a class, without any side effects

R2021a 以降

説明

ルール定義

Move and copy constructors shall move and respectively copy base classes and data members of a class, without any side effects.

根拠

移動コンストラクターとコピー コンストラクターの想定される動作は次のとおりです。

  • これらのコンストラクターは、基底クラスとデータ メンバーを移動またはコピーします。

  • 移動コンストラクターは、ソース オブジェクトを有効な状態に設定します。

二次的影響のある移動コンストラクターまたはコピー コンストラクターを作成すると、次の問題を引き起こす可能性があります。

  • パフォーマンス:移動コンストラクターとコピー コンストラクターは、標準テンプレート ライブラリ (STL) のアルゴリズムとコンテナーから頻繁に呼び出されます。二次的影響によって引き起こされるこれらのコンストラクターのパフォーマンス オーバーヘッドが蓄積し、コードのパフォーマンスに影響する可能性があります。

  • 予期しない動作:コンパイラがコードを最適化するためにコピー コンストラクターへの呼び出しを省略する場合があるため、コピー コンストラクターが呼び出される回数は不確定です。そのため、コピー コンストラクターの二次的影響が予期せぬ動作を招く可能性があります。

Polyspace 実装

コピー コンストラクターまたは移動コンストラクターの本体で、Polyspace® は次のような演算にはフラグを設定しません。

  • コピー代入または移動代入。

  • 関係演算または比較演算。

  • 移動演算でのソース オブジェクトの変更。

  • 関数 std::swap または等価なユーザー定義 noexceot スワップ関数の呼び出し。Polyspace はシグネチャが void T::swap(T&) または void [N::]swap(T&, T&) である関数をスワップ関数として識別します。最初のシグネチャは、1 つの引数を取るクラス T のメンバー関数を表します。2 番目のシグネチャは、2 つの引数を取る名前空間 N 内の非メンバー関数または静的関数を表します。swap という名前の大文字と小文字は区別されず、先頭または末尾にアンダースコアを付加できます。

  • 変数 static の代入と変更。

Polyspace は、コピー コンストラクターまたは移動コンストラクター内の他の演算に望ましくない二次的影響としてフラグを設定します。たとえば、ユーザー定義スワップ関数が noexcept ではない場合、そのスワップ関数の呼び出しは望ましくない二次的影響と見なされます。コピー代入演算子と移動代入演算子に関する同様のルールについては、AUTOSAR C++14 Rule A6-2-1 を参照してください。

トラブルシューティング

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

すべて展開する

次のコードでは、二次的影響がある移動コンストラクターとコピー コンストラクターに Polyspace がどのようにフラグを設定するかを示します。

#include<cstdint>
#include <utility>
#include<iostream>
class B
{
public:
	// Implementation
	B(B&& oth) : ptr(std::move(oth.ptr)) // Noncompliant
	{
		oth.ptr = nullptr; // Does not have a side effect
		std::cout<<"Moved"; //Has a side effect
	}
	~B()
	{
		delete ptr;
	}

private:
	std::int32_t* ptr;
};
class C
{
public:
	C(int t=0) : x(t) {}
	C(const C& oth): x(oth.x)  // Noncompliant
	{
		//...
		x = oth.x % 2;  // Has a side effect
		count++; //Not a side effect
	}

private:
	std::int32_t x;
	static std::int32_t count;
};
class D
{
public:

	D(const D& oth): x(oth.x)  // Noncompliant
	{
		D tmp(oth);
		_swap_(tmp);
	}
	void _swap_(D& rhs){ //Might raise exceptions
		//...
	}
private:
	std::int32_t x;
	static std::int32_t count;
};

  • 二次的影響として、クラス B の移動コンストラクターは、出力ストリームに文字列を出力します。この二次的影響は、移動演算にパフォーマンス オーバーヘッドを生じさせます。Polyspace は、移動代入演算子にフラグを設定し、ステートメントを強調表示します。移動元オブジェクト oth.ptrnullptr への設定は二次的影響ではありません。

  • クラス C のコピー コンストラクターは、ソース オブジェクトのデータ メンバー x を変更します。この二次的影響はパフォーマンス オーバーヘッドを生じさせます。移動演算中およびコピー演算中にデータ メンバーへの想定外の変更があると、コードを標準テンプレート ライブラリと非互換にし、開発中のエラーを生じさせます。Polyspace はコピー代入演算子にフラグを設定し、ステートメント x = oth.x % 2 を強調表示します。静的変数 count のインクリメントは二次的影響ではありません。

  • クラス D のコピー コンストラクターは、_swap_ という名前のユーザー定義スワップ関数を呼び出します。このスワップ関数は noexcept ではありません。_swap_ から例外が発生した場合は、この例外がコピー コンストラクターの予期しない二次的影響です。Polyspace は、このルールに非準拠としてコピー コンストラクターにフラグを設定します。noexcept であるユーザー定義スワップ関数を使用してください。

チェック情報

グループ: 特殊なメンバー関数
カテゴリ: Required、Automated

バージョン履歴

R2021a で導入