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

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

Описание

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

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

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

Это средство проверки не повышено когда выход std::string::c_str используется в строковых операциях кроме неявной и явной конструкции.

Риск

Это дорого и неэффективно, чтобы использовать струну до выход 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());
	bar( other.c_str() ); 
	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);
}

Проверяйте информацию

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