Expensive constant std::string construction

const объект строки создается форма постоянные данные, приводящие к неэффективному коду

Описание

Этот дефект происходит когда const std::string объект создается из постоянных данных. Например, этот дефект повышен, когда вы создаете const std::string объект от строкового литерала или constexpr функция. Это средство проверки не отмечает non-const std::string объекты, переменные члена класса и строковые литералы, которые являются аргументами функции.

Риск

Когда const std::string объекты создаются из постоянного содержимого в функции или блоке кода, новом std::string объект создается с тем же содержимым каждый раз, когда блок функции или кода выполняется. Такой код приводит к повторной конструкции std::string объект без модификации содержимого, которое неэффективно. Рассмотрите этот код:

#include <string>
constexpr char const* getStrPtr() { 
	return "abcd"; 
}
void foo(){
	const std::string s1 = "abcd";
	const std::string s2{"abcd"};
	const std::string s3 = getStrPtr();                 
}
int main(){
//...
for(int i = 0; i<10000; ++i)
      foo();
}
В этом коде, функциональном foo называется 10000 \times. Каждый раз foo называется, s1S2 , и s3 создаются из того же литерала постоянной строки abcd, получившийся в неэффективном коде. Также не ясно, предназначил ли разработчик три объекта строки представлять те же данные. Поскольку такой неэффективный и запутывающий код компилирует и функционирует правильно, конструкция const std::string объекты из постоянных данных не могут быть замечены.

Фиксация

Фиксация для этого дефекта зависит от надлежащего использования постоянных данных.

  • Можно хранить постоянные данные в static представьте объект в виде строки, если вам нужны функциональности std::string класс.

  • Можно использовать постоянные данные непосредственно в качестве временных объектов, если вы не должны снова использовать данные.

  • Можно хранить постоянные данные при помощи const символьный массив или std::string_view возразите, не ли вам нужны функциональности std::string класс. std::string_view поддерживается C++ 17 и позже.

Рассмотрите этот код:

constexpr char const* getStrPtr() { 
	return "abcd"; 
}
void foo(){
	static const std::string s3 = getStrPtr();
	 std::string_view s3a{s3};                
}
int main(){
//...
for(int i = 0; i<10000; ++i)
      foo();
}
const std::string объект s3 объявляется как static. Поскольку s3 static, это создается только однажды даже если foo называется 10000 \times. std::string_view объект s2 показывает содержимое s3 и старается не создавать std::string возразите каждый раз foo называется. При помощи std::string_view и static объекты, вы избегаете ненужного копирования постоянных данных. Этот метод разъясняет что объекты s3 и s3a представляйте те же данные.

Примеры

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

#include <string>
constexpr char const* getStrPtr() { 
	return "abcd"; 
}
constexpr size_t FOUR(){
	return 4; 
}
const size_t getCount();
void CallFunc(const std::string s);
void foo(){
	const std::string s1 = "abcd";
	const std::string s2{"abcd"};
	const std::string s3 = getStrPtr();  
	const std::string s4("abcd", FOUR());
	const std::string s5("abcd"), s6("abcd");
}

void bar(){
	const std::string s3a("abcd", getCount());
	std::string s7 = "abcd";
	const char *p = "abcd";
	const std::string s_p = p;
      CallFunc("message");
}

В этом примере, нескольких const std::string объекты объявляются.

  • Polyspace® отмечает const std::string объекты s1S2 , s5, и s6 потому что, если эти строки создаются из постоянных данных каждый раз foo называется.

  • Polyspace flagss4 и s3 потому что они создаются из констант времени компиляции, таких как постоянный литеральный abcd и выход constexpr функция. Объект s3a не отмечается потому что выход getCount не постоянное время компиляции.

  • Polyspace не отмечает эти объекты, когда они создаются из постоянных данных:

    • std::string объект, который не объявляется как const, такой как s7.

    • Объект, который не является std::string, такой как *p.

    • Временные объекты, которые создаются как аргумент функции, такой как объект, содержащий строковый литерал message в аргументе CallFunc.

Коррекция

можно зафиксировать этот дефект несколькими способами. Например:

  • Можно объявить const std::string как static. Когда объектом является static, компилятор не восстанавливает его в различных осциллографах. Когда вам нужны функциональности std::string класс, это объявление является хорошей фиксацией.

  • Можно хранить постоянные данные в символьном массиве или символьном указателе. Эти объекты являются менее дорогими по сравнению с std::string.

  • Можно объявить постоянные строки как std::string_view объекты. Эти объекты не содержат копию постоянных строк, которая делает эти объекты эффективными.

#include <string>
#include <string_view>
constexpr char const* getStrPtr() { 
	return "abcd"; 
}
constexpr size_t FOUR(){
	return 4; 
}

void foo(){
	static const std::string s1 = "abcd";
	const std::string_view s2{s1};
	const char *p = getStrPtr();
	const std::string s3 = p;
	static const std::string s4("abcd", FOUR());
	const std::string_view s5(s1), s6("s4");
}

Проверки на s1 и s4 фиксируются путем объявления их как static. Проверки на s2, s5 и s6 фиксируются путем объявления их как std::string_view объекты. Проверка на s3 фиксируется, храня постоянные данные в символьном указателе.

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

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