cppcheck - スタイルの意味 - noConstructor ~ variableScope

クラウディア 
noConstructor
noCopyConstructor
noExplicitConstructor
noOperatorEq
redundantAssignment
redundantCondition
unreachableCode
unreadVariable
unusedStructMember
variableScope

noConstructor

ID:noConstructor
The class 'クラス名' does not have a constructor.
 「クラスにコンストラクタが存在しない」と言っているようです。  これが出力されたソースでは、実際にはコンストラクタは存在しているのです。  C/C++ でなく CLI のソースで「public ref class クラス名'」というクラス定義であることが原因なのか?  よくわかっていません。

noCopyConstructor

ID:noCopyConstructor
Class 'クラス名' does not have a copy constructor which is recommended since it has dynamic memory/resource allocation(s).
#include <limits.h>
#include <stdio.h>

class Sample
{
public:
	Sample(const char *aname);
	virtual ~Sample(void);

private:
	FILE *pread;								// ファイル
};

Sample::Sample(const char *aname)
{
	char  afile[PATH_MAX];						// ファイル名

	sprintf(afile, "%s.c", aname);

	if ((pread = fopen(afile, "r")) == NULL)
	{
		perror(afile);
		return;
	}
}

Sample::~Sample(void)
{
	fclose(pread);
}

 上記のソースの 20行目でチェックにかかります。  ん~よくわからないのです。「コピーコンストラクタを持っていないのに動的なリソースを持ってんじゃん」って言っているようには見えるのですが・・・。  よくわからないままに、コピーコンストラクタだか、operator= だかをいれてやってこんなソースにするとメッセージは出力されなくなるんですがね。
#include <limits.h>
#include <stdio.h>

class Sample
{
public:
	Sample(const char *aname);
	Sample::Sample(const Sample& other);
	virtual ~Sample(void);

	Sample &operator=(const Sample &other)
	{
		if (this != &other)
		{
			pread = other.pread;
		}

		return *this;
	}

private:
	FILE *pread;								// ファイル
};

Sample::Sample(const Sample& other)
{
	this->pread = other.pread;
}

Sample::Sample(const char *aname)
{
	char  afile[PATH_MAX];						// ファイル名

	sprintf(afile, "%s.c", aname);

	if ((pread = fopen(afile, "r")) == NULL)
	{
		perror(afile);
		return;
	}
}

Sample::~Sample(void)
{
	fclose(pread);
}

 今度はこっちの 27行目が「copyCtorPointerCopying」ってのになっちゃうんだな。

noExplicitConstructor

 これは、バージョン 1.81 では、警告だったはずなのですが 1.85 ではスタイルになっちゃってます。
ID:noExplicitConstructor
Class 'クラス名' has a constructor with 1 argument that is not explicit. Such constructors should in general be explicit for type safety reasons. Using the explicit keyword in the constructor means some mistakes when using the class can be avoided.
#include <limits.h>
#include <stdio.h>

class Sample
{
public:
	Sample(const int a);
	virtual ~Sample(void);

private:
	int a_;
};

Sample::Sample(const int a)
{
	a_ = a;
}

Sample::~Sample(void)
{
}

 7行目があかんと言われます。  これが、実はよくわかっていないのですが、警告の発生したクラスは、引数のあるコンストラクタが存在します。これが not explicit 明確に定義されていない?  宣言はあるのですが・・・。  とりあえず、無視しちゃっています。

noOperatorEq

ID:noOperatorEq
Class 'Sample' does not have a operator= which is recommended since it has dynamic memory/resource allocation(s).
 「noCopyConstructor」と同じソースで出現しました。
#include <limits.h>
#include <stdio.h>

class Sample
{
public:
	Sample(const char *aname);
	virtual ~Sample(void);

private:
	FILE *pread;								// ファイル
};

Sample::Sample(const char *aname)
{
	char  afile[PATH_MAX];						// ファイル名

	sprintf(afile, "%s.c", aname);

	if ((pread = fopen(afile, "r")) == NULL)
	{
		perror(afile);
		return;
	}
}

Sample::~Sample(void)
{
	fclose(pread);
}

 「operator=」がないっちゅうんでしょうなぁ。  これも「noCopyConstructor」と同じ手当で一応、消えます。

redundantAssignment

ID:redundantAssignment
Variable '変数名' is reassigned a value before the old one has been used.
 redundantCopy ってやつとよく似ているんですが

    int a = 1.0;

    なんだかんだの処理の記述
    しかしその処理で一度も a は使用していない

    a = 2.0;
 てなコードを書いていると出力されます。  「変数 a に何か設定しているけど、それなんにも使わないうちに別の値をいれてるじゃね~かよ」と言っているようです。  まぁ、納得できる話ですね。

redundantCondition

ID:redundantCondition
Redundant condition: If '変数名 > 値1', the comparison '変数名 > 値2' is always true.
 例えばこういうコードだと
void sub(int a)
{
	if ((a > 10) || (a > 100))
	{
		sub2(a);
	}
}

 3行目の if 文で、a が 100 より大きい数だとして、(a > 10) はそうなれば常に真になっちゃうよ、その条件に意味はあるのかい?  ってことです。

unreachableCode

ID:unreachableCode
Statements following return, break, continue, goto or throw will never be executed.
void sub(int a)
{
	int b;

	switch(a)
	{
	case 1:
		break;

	case 2:
		break;
		b = 0;

	default:
		break;
	}
}

 てなコードを書いてあると。  12行目は、絶対に実行することのないコードなのでこのメッセージが出力されます。  cppcheck でなくともコンパイルの時点で警告が表示されるでしょうね。

unreadVariable

ID:unreadVariable
Variable '変数名' is assigned a value that is never used.
 該当の変数名について、宣言・初期化はあるものの、使用していない場合に出力されます。  ソースを変更して、処理をコメントアウトした結果、変数宣言だけが残ったりすること。ありませんか?

void sub(void)
{
	int a;
	int i;

	for (i=0; i<10; i++)
	{
		a = 0;

		・・・
	}

	return;
}
 以前は、10行目以降に、a に対する条件文や何かがあったのにコメントアウトしてしまって結果、こういうことになってしまった・・・とか。

unusedStructMember

ID:unusedStructMember
struct member '構造体タグ::メンバ名' is never used.

struct tagA
{
	int n1;
	int n2;
} strVal;
 てな定義をしている関数で、n1 しか使っていないとすると、n2 の方にこんなメッセージが出ちゃうのです。  しかし、これはどうなんだろう?  実際、このメッセージが出たソースでは、別の関数にアドレス渡しをして、渡された関数の方で利用しているのですが・・・。

variableScope

ID:variableScope
The scope of the variable '変数名' can be reduced.
 メッセージに具体例が記述されているのですが

void f(int x)
{
    int i = 0;

    if (x)
    {
        //	it's safe to move 'int i = 0;' here

        for (int n = 0; n < 10; ++n)
        {
            //	it is possible but not safe to move 'int i = 0;' here

            do_something(&i);
        }
    }
}
 do_something 内で、i の値は変化していくわけで・・・。  変化を期待しているのであれば、ループの外だろうし、条件文の下にさらにそれを使うのであれば、条件文の外だろうし、do_something を呼ぶごとに i が 0 であることを期待するのであれば、ループ内だろうし。  変数の使い方ではないか?と思っているのですが・・・。
ハイスピードプランマイニングベース