Main Content

Expensive use of std::string method instead of more efficient overload

An std::string method is called with a string literal of known length, instead of a single quoted character

Since R2021a

Description

This defect occurs when you invoke certain std::string methods with a string literal of known length instead of a single quoted character. When certain std::string methods are called with a string literal, the method must compute the length of the literal even though the information is known at compile time. Polyspace flags such calls as inefficient. For instance, Polyspace® flags the first two calls to std::string::find:

std::string str;
//...
str.find("A");//Inefficient
//...
str.find("ABC",offset,1);//Inefficient
str.find('A');//Efficient
In the first two calls, the compiler computes the length of the string literal "A" when it is already known before runtime. In the third call, the compiler does not compute the length of the input, making the call more efficient than the first two. Polyspace raises this defect when these std::string methods are invoked by using a string literal of known length instead of a single quoted character:

  • 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)

Risk

In some cases, you can call std::string methods with either a string literal or a single quoted character. In these cases, it is inefficient to call the std::string methods with string literal because such calls force the compiler to compute the lengths of the string literals, which is already known before runtime. Because std::string methods are frequently used, inefficient calls to these methods might result in expensive and inefficient code.

Fix

To fix this issue, call the std::string methods by using single quoted characters instead of a string literal when appropriate. For instance, you might use a single quoted character as an input instead of a string literal consisting of a single character or a repetition of a single character. You might need to use a different overload of the method that accepts a single quoted character.

Performance improvements might vary based on the compiler, library implementation, and environment that you are using.

Examples

expand all

#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);
}

In this example, several methods and operators of the std::string class are invoked to perform string operations. For these calls, you already know the length of the string literals before program runtime. Because the input is passed as a string object, the compiler performs a linear search to find its length, which is redundant. Polyspace flags such inefficient invocation of string operations.

Correction – Use Overloads that Accepts char as Input

To fix this issue, use a single quoted character instead of a string literal. For methods such as replace, rewrite the function call and use the overload that accepts char type variables when the input is a single character.

#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');
}

Result Information

Group: Performance
Language: C++
Default: Off
Command-Line Syntax: EXPENSIVE_USE_OF_STD_STRING_METHODS
Impact: Low

Version History

Introduced in R2021a