Expensive std::string::c_str() use in a std::string operation

Строковая операция использует выход std::string::c_str метод, приводящий к неэффективному коду

Описание

Этот дефект происходит, когда строковая операция выполняется при помощи указателя струны до, полученного из std::string::c_str. Например, это средство проверки повышено когда:

  • Новый std::string или std::wstring неявно или явным образом создается из выхода соответствующего c_str. Эта ситуация возникает когда функция, ожидая const ссылка на строку сталкивается с const char* вместо этого.

  • Новая копия объекта строки создается явным образом из выхода своего c_str функция. Используя копию конструктор является более эффективным способом скопировать объект строки.

  • Определенный std::string функции членства вызываются при помощи выхода std::string::c_str. Отмеченные функции включают replaceдобавление, assignСравнение, и find. Используя std::string возразите непосредственно, чтобы вызвать std::string функции членства более эффективны.

  • Пользовательская функция, которая перегружается, чтобы принять любой из const char* и const std::string аргументы вызываются при помощи указателя струны до. Более эффективно вызвать std::string перегрузка такой функции.

Риск

Это дорого и неэффективно, чтобы использовать струну до выход std::string::c_ctr метод, когда можно использовать std::string объект вместо этого. std::string объект содержит длину строки. Когда вы используете струну до выход std::string::c_str метод вместо std::string объект, конструктор определяет длину струны до линейным поиском, приводящим к неэффективному коду. Используя std::string::c_str является также часто ненужным. Рассмотрите этот код:

void set_prop1(const char* str);
void set_prop2(const std::string& str);
void foo( std::string& str){
	//...
	set_prop1(str.c_str()); // Necessary
	//...
	set_prop2(str.c_str()); // Inefficient	
}
Функциональный foo вызывает две различных функции. Поскольку функциональный set_prop1 требует струны до как входа, с помощью str.c_str функция необходима, чтобы сформировать вход к set_prop1. Функциональный set_prop2 берет std::string как вход. Вместо того, чтобы непосредственно использовать str как вход к set_prop2, str.c_str используется, возможно, как ошибка вставки копии. Компилятор неявно создает новый std::string объект, который идентичен str, при помощи выхода str.c_str. Построение нового std::string объект в этом случае является ненужным и неэффективным. Поскольку этот код компилирует и функционирует правильно, этот неэффективный код не может быть замечен.

Фиксация

Чтобы зафиксировать этот дефект, замените вызовы std::string::c_str std::string. Рассмотрите этот код:

void set_prop1(const char* str);
void set_prop2(const std::string& str);
void foo( std::string& input){
	//...
	set_prop1(str.c_str()); // Necessary
	//...
	set_prop2(str); // Efficient	
}
Используя str вместо str.c_str как введено к set_prop2 делает код более эффективным и фиксирует дефект.

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

Примеры

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

#include <string>
#include <utility>

class A
{
public:
	A( char const* );
	char const* c_str() const;
};
void CppLibFuncA(const std::string&);
void CppLibFuncB(std::string &&);
void bar( A const& );
std::string make_string();
bool contains( std::string const& str1, std::string const& str2 )
{
	return str1.find( str2.c_str() ) == std::string::npos;
}

void foo(const std::string& s, std::string&& rs, A& other){
	CppLibFuncA( s.c_str() ); 
	CppLibFuncB( std::move( rs ).c_str() ); 
	CppLibFuncA( make_string().c_str() ); 
	bar( other.c_str() ); 
	if(contains(s,make_string())){
		//...
	}
}

В этом примере Polyspace® отмечает неявное использование std::string::c_str создать std::string объект при вызывании функций.

  • Функциональный CppLibFuncA берет const std::string& как введено. Когда функциональный CppLibFunc называется при помощи s.c_str(), компилятор не может передать ссылку на s к функции. Вместо этого компилятор неявно создает новый std::string объект от указателя струны до и передают новый объект функции, которая неэффективна. Polyspace отмечает вызов std::string::c_str.

  • Поскольку вызов CppLibFuncB при помощи выхода std::string::c_str также неявно создает новый str::string объект, Polyspace отмечает вызов std::string::c_str.

  • Вызов функционального bar не отмечается потому что const char* неявно не преобразован в новый std::string объект.

  • Polyspace не отмечает использование std::string::c_str в операциях кроме конструкции. Вызов std::string::find(), где выход std::string::c_str используется вместо std::string возразите, не отмечается.

Коррекция

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

#include <string>
#include <utility>
void CppLibFuncA(std::string const &);
void CppLibFuncB(std::string &&);
std::string make_string();
bool contains( std::string const& str1, std::string const& str2 )
{
	return str1.find( str2 ) == std::string::npos;
}
void foo(std::string const & s, std::string&& rs){
	CppLibFuncA( s ); 
	CppLibFuncB( std::move( rs ) ); 
	CppLibFuncA( make_string()); 
	if(contains(s,make_string())){
		//...
	}	
}

Зафиксируйте вызовы функций CppLibFunc, CppLibFuncB, и CppLibFuncC путем удаления вызова std::string::c_str и вместо этого с помощью существующего std::string объекты, как введено.

#include <string>
#include <utility>
std::string make_string(void);
void bar(const std::string& s){
	std::string s1 = s.c_str(); // Inefficient
	std::string s2 = make_string();
	s2.append(s1.c_str());
}

В этом примере Polyspace отмечает явное использование std::string::c_str скопировать std::string объекты к s1. Содержимое s1 также добавлен к s2 при помощи s1.c_str(). Polyspace отмечает использование струны до в std::string::append() функция.

Коррекция

Чтобы устранить эту проблему, избегайте использования std::string::c_str когда можно использовать std::string объект.

#include <string>
#include <string>
#include <utility>
std::string make_string(void);
void bar(const std::string& s){
	std::string s1 = s; // Efficient
	std::string s2 = make_string();
	s2.append(s1);
}
#include <string>
#include <utility>
std::string make_string(void);
void bar( std::string& s1){
	std::string s2 = make_string();
	s1.replace(1, 1, s2.c_str());               
	s1.replace(s1.begin(), s1.end(), s2.c_str());   
	s1.append(s2.c_str());                          
	s1.assign(s2.c_str());                         
	s1.compare(s2.c_str());                        
	s1.find(s2.c_str());                            
}

В этом примере Polyspace отмечает явное использование std::string::c_str вызвать функции членства std::string класс.

Коррекция

Чтобы устранить эту проблему, избегайте использования std::string::c_str когда можно использовать std::string объект вместо этого.

#include <string>
#include <string>
#include <utility>
std::string make_string(void);
void bar( std::string& s1){
	std::string s2 = make_string();
	s1.replace(1, 1, s2);               
	s1.replace(s1.begin(), s1.end(), s2);   
	s1.append(s2);                          
	s1.assign(s2);                         
	s1.compare(s2);                        
	s1.find(s2);                            
	s1.find(s2); 
}
#include <string>
#include <utility>
extern void userDefined(const char *);
extern void userDefined(const std::string &);
void bar( const std::string& s){
	const char* p = s.c_str();    
	userDefined(p);
	userDefined(s.c_str());                         
}

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

Коррекция

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

#include <string>
#include <string>
#include <utility>
extern void userDefined(const char *);
extern void userDefined(const std::string &);
void bar( const std::string& s){                       
	userDefined(s);                     
}

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

Группа: Производительность
Язык: C++
Значение по умолчанию: Off
Синтаксис командной строки: EXPENSIVE_C_STR_STD_STRING_OPERATION
Удар: Средняя
Введенный в R2020b