メインコンテンツ

空の文字列リテラルに対する計算量の多い std::string の使用

空の文字列リテラルに対して std::string を使用する代わりに、より計算量の少ないメンバー関数 std::basic_string の呼び出しができる

R2021a 以降

説明

C/C++ コードでは、チェッカーは以下の演算にフラグを設定します。

  • 空の文字列リテラルを使用した std::string インスタンスの構築

  • std::string インスタンスへの空の文字列リテラルの代入

  • 空の文字列リテラルとの std::string インスタンスの比較

使用法のメモと制限:

  • チェッカーは、空の状態であり、最終的に std::string で使用されるポインター変数 const char の接続元を追跡しません。

  • 現在のコンパイラを使用する場合、このチェッカーは部分的に旧式です。GCC 5.1 や Visual Studio® 2015 などのコンパイラは、空の文字列リテラルを除外して構成を最適化し、既定の構成と同一として扱います。

リスク

上記の演算は、std::basic_string クラス テンプレートの既定のコンストラクターとメンバー関数 empty および clear の呼び出しに置き換えることができます。コンパイラによっては、組み込みメンバー関数を使用する場合との比較で、明示的演算の追加命令を生成する場合があります。これらの演算を使用すると、コンパイルされたコードのパフォーマンスが低下する可能性があります。

修正方法

空の文字列リテラルを含む明示的演算を、std::basic_string の既定のコンストラクターとメンバー関数の呼び出しで置き換えます。

使用を回避使用
std::string s(""); std::string s;
std::string s = ""; std::string s;
s = ""; s.clear();
if (s == "") if (s.empty())
return ""; return {};
void foo(const std::string& s = "");void foo(const std::string& s = {});(C++11) または foo(const std::string &str2 = std::string())
foo(""); foo({}) (C++11) または foo(std::string())
Class::Class() : str("") {//...} Class::Class() : str() {//...}

パフォーマンスの改善の程度は、使用しているコンパイラ、ライブラリ実装、環境によって異なる可能性があります。

すべて展開する

#include <iostream>
#include <string>

void compareString(const std::string &str1, const std::string &str2="")//Noncompliant
{
	if (str1 == "")//Noncompliant
	{
		std::cout << "The string is empty" << std::endl;
	}
	else
	{
		if (str1.compare(str2) != 0)
		std::cout << str1 << " is not " << str2 << '\n';
	}
}


void bar(){
	compareString("String1");
	compareString("String1","");//Noncompliant
}
この例では、3 つの文字列操作を行うために、空の文字列リテラルが使用されています。Polyspace はこれらの演算に対し、非効率としてフラグを設定します。

修正 — std::string のメンバー関数を使用

フラグが設定された問題を修正するには、空の文字列リテラルを使用する文字列操作を、std::string のメンバー関数の呼び出しで置き換えます。次に例を示します。

  • const std::string &str2=""const std::string &str2={} で置き換えます。

  • if(str1 == "")if(str1.empty()) で置き換えます。

  • compareString("String1","")compareString("String1",{}) で置き換えます。

#include <iostream>
#include <string>

void compareString(const std::string &str1, const std::string &str2 = {})//Compliant
{
	if (str1.empty())//Cmpliant
	{
		std::cout << "The string is empty" << std::endl;
	}
	else
	{
		if (str1.compare(str2) != 0)
		std::cout << str1 << " is not " << str2 << '\n';
	}
}


void bar(){
	compareString("String1");
	compareString("String1",{});//Compliant
}

結果情報

グループ: パフォーマンス
言語: C++
既定値: オフ
コマンド ライン構文: UNNECESSARY_EMPTY_STRING_LITERAL
影響度: Low

バージョン履歴

R2021a で導入