exponenta event banner

Дорогостоящее использование std::string методы вместо более эффективной перегрузки

Один std::string метод вызывается со строковым литералом известной длины вместо одного символа в кавычках

Описание

Этот дефект возникает при вызове определенного std::string методы со строковым литералом известной длины вместо одного символа в кавычках. При определенных std::string методы вызываются со строковым литералом, метод должен вычислять длину литерала, даже если информация известна во время компиляции. Polyspace помечает такие вызовы как неэффективные. Например, Polyspace ® помечает первые два вызова std::string::find:

std::string str;
//...
str.find("A");//Inefficient
//...
str.find("ABC",offset,1);//Inefficient
str.find('A');//Efficient
В первых двух вызовах компилятор вычисляет длину строкового литерала «A», когда он уже известен до выполнения. В третьем вызове компилятор не вычисляет длину ввода, делая вызов более эффективным, чем первые два. Polyspace поднимает этот дефект, когда они std::string методы вызываются с использованием строкового литерала известной длины вместо одного символа в кавычках:

  • find

  • rfind

  • find_first_of

  • find_last_of

  • find_first_not_of

  • find_last_not_of

  • replace

  • operator=

  • operator+=

  • starts_with (C++ 20)

  • ends_with (C++ 20)

Риск

В некоторых случаях можно позвонить std::string методы со строковым литералом или одиночным символом в кавычках. В этих случаях неэффективно вызывать std::string методы со строковым литералом, поскольку такие вызовы заставляют компилятор вычислять длины строковых литералов, которые уже известны до выполнения. Поскольку std::string часто используются методы, неэффективные вызовы этих методов могут привести к дорогостоящему и неэффективному коду.

Зафиксировать

Чтобы устранить эту проблему, позвоните в std::string с помощью одиночных кавычек вместо строкового литерала. Например, в качестве ввода вместо строкового литерала, состоящего из одного символа или повторения одного символа, можно использовать один символ в кавычках. Возможно, потребуется другая перегрузка метода, который принимает один знак в кавычках.

Повышение производительности может зависеть от используемого компилятора, реализации библиотеки и среды.

Примеры

развернуть все

#include <string>
#include <set>
constexpr size_t ONE(){ return 1; }
void foo(std::string& str){
	int pos, count;
	str += "A";
	str += "\0";
	str.find("AA", 0, ONE());
	str.find("A");
	str.find_first_of("A");
	str.find_last_of("A"); 
	str.find_first_not_of("A");
	str.find_last_not_of("A");
	str.replace(0, 1, "A");
	str.rfind("AA", 0,1);
	str.replace(0, count, "AAAAA");
	str.replace(pos, count, "AB", 1);
}

В этом примере несколько методов и операторов std::string вызывается для выполнения строковых операций. Для этих вызовов вы уже знаете длину строковых литералов перед выполнением программы. Поскольку входные данные передаются как строковый объект, компилятор выполняет линейный поиск, чтобы найти его длину, которая является избыточной. Polyspace помечает такой неэффективный вызов строковых операций.

Коррекция - использовать перегрузки, принимающие char в качестве входных данных

Чтобы устранить эту проблему, используйте один символ в кавычках вместо строкового литерала. Для таких методов, как replace, перезаписать вызов функции и использовать перегрузку, которая принимает char введите переменные, если входные данные являются одним символом.

#include <string>
#include <set>
constexpr size_t ONE(){ return 1; }
void foo(std::string& str){
	int pos, count;
	str += 'A';
	str += '\0';
	str.find('A');
	str.find_first_of('A');
	str.find_last_of('A'); 
	str.find_first_not_of('A');
	str.find_last_not_of('A');
	str.replace(0, 1, 1,'A');//Rewritten call that accepts a single char
	str.rfind('A');
	str.replace(0, count, 5,'A');//Rewritten call that accepts a single char
	str.replace(pos, count, 1,'A');
}

Информация о результатах

Группа: Производительность
Язык: C++
По умолчанию: Откл.
Синтаксис командной строки: EXPENSIVE_USE_OF_STD_STRING_METHODS
Воздействие: Низкий
Представлен в R2021a