Если я возвращаю станд.:: строки?

self.__dict__.update(kwargs)

65
задан Pedro d'Aquino 23 June 2009 в 12:27
поделиться

12 ответов

Вернуть строку.

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

Потребовалось много лет, чтобы получить хорошую абстракцию строк в C ++. Я не верю, что Бьярн Страуструп, столь известный своим консервативным изречением «плати только за то, что ты используешь», допустил бы явное убийство производительности в языке. Высшая абстракция - это хорошо.

63
ответ дан 24 November 2019 в 15:25
поделиться

Похоже, хорошая идея.

Если это не часть программного обеспечения реального времени (например, игра), а обычное приложение, с вами все будет более чем хорошо.

Помните, « Преждевременная оптимизация - корень всех зол »

10
ответ дан 24 November 2019 в 15:25
поделиться

В вашем случае будет произведена оптимизация возвращаемого значения, поэтому std :: string не будет скопирован.

5
ответ дан 24 November 2019 в 15:25
поделиться

Я согласен с duffymo. Сначала нужно сделать понятное работающее приложение, а потом, при необходимости, оптимизировать атаку. Именно в этот момент вы поймете, где находятся основные узкие места, и сможете более эффективно управлять своим временем при создании более быстрого приложения.

1
ответ дан 24 November 2019 в 15:25
поделиться

Я согласен с @duffymo. Не оптимизируйте, пока не проведете измерения, это верно вдвойне при выполнении микрооптимизации. И всегда: измеряйте до и после , которую вы оптимизировали, чтобы увидеть, действительно ли вы изменили ситуацию к лучшему.

1
ответ дан 24 November 2019 в 15:25
поделиться

Верните строку, это не такая уж большая потеря производительности, но наверняка облегчит вашу работу впоследствии.

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

1
ответ дан 24 November 2019 в 15:25
поделиться

Вернуть строку, как все говорят.

при принятии строк в качестве параметров должен ли я получать их как const std :: string & или const char * ?

Я бы сказал, принимайте любые константные параметры по ссылке, если только они не достаточно легкие, чтобы принимать по значению, или в тех редких случаях, когда вам нужен нулевой указатель в качестве действительного ввода, означающего «ничего из вышеперечисленного». Эта политика не специфична для строк.

Неконстантные ссылочные параметры спорны, потому что из вызывающего кода (без хорошей IDE) вы не можете сразу увидеть, являются ли они re передается по значению или по ссылке, и разница важна. Так что код может быть непонятным. Для параметров const это не применимо. Люди, читающие вызывающий код, обычно могут просто предположить, что это не их проблема, поэтому им нужно будет только время от времени проверять подпись.

В случае, когда вы собираетесь взять копию аргумента в функции, ваш общая политика должна заключаться в том, чтобы принимать аргумент по значению. Тогда у вас уже есть копия, которую вы можете использовать, и если вы бы скопировали ее в какое-то определенное место (например, член данных), вы можете переместить ее (в C ++ 11) или поменять местами (в C ++ 03) на получить это там. Это дает компилятору наилучшую возможность оптимизировать случаи, когда вызывающий объект передает временный объект.

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

14
ответ дан 24 November 2019 в 15:25
поделиться

Это человеческая природа - беспокоиться о производительности, особенно когда язык программирования поддерживает оптимизацию низкого уровня. Однако мы, программисты, не должны забывать, что производительность программы - это лишь одна из многих вещей, которые мы можем оптимизировать и восхищаться ею. Помимо скорости программы, мы можем найти красоту в собственном исполнении. Мы можем свести к минимуму наши усилия, пытаясь добиться максимального визуального вывода и интерактивности пользовательского интерфейса. Как вы думаете, это могло быть больше мотивацией, чем беспокойство о битах и ​​циклах в долгосрочной перспективе ... Так что да, верните строку: s. Они минимизируют размер вашего кода и ваши усилия, а также делают объем работы, которую вы выполняете, менее удручающей.

6
ответ дан 24 November 2019 в 15:25
поделиться

Стоимость копирования строк по значению зависит от реализации STL, с которой вы работаете:

  • std :: string в MSVC использует оптимизацию коротких строк, так что короткие строки (<16 символов iirc) не требуют выделения памяти (они хранятся внутри самой std :: string), а более длинные требуют выделения кучи при каждом копировании строки.

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

В общем, вам лучше просто забыть о вышеизложенном и возвращать std :: strings по значению, если вы не делаете это тысячи раз в секунду.

re: передача параметров, имейте в виду, что есть стоимость перехода от char * -> std :: string, но не от перехода от std :: string-> char *. В общем, это означает, что вам лучше принять константную ссылку на std :: string. Однако лучшее оправдание для принятия в качестве аргумента const std :: string & состоит в том, что тогда вызываемому лицу не нужно иметь дополнительный код для проверки по сравнению с null.

но не от перехода от std :: string-> char *. В общем, это означает, что вам лучше принять константную ссылку на std :: string. Однако лучшее оправдание для принятия в качестве аргумента const std :: string & состоит в том, что тогда вызываемому лицу не нужно иметь дополнительный код для проверки по сравнению с null.

но не от перехода от std :: string-> char *. В общем, это означает, что вам лучше принять константную ссылку на std :: string. Однако лучшее оправдание для принятия в качестве аргумента const std :: string & состоит в том, что тогда вызываемому лицу не нужно иметь дополнительный код для проверки по сравнению с null.

12
ответ дан 24 November 2019 в 15:25
поделиться

Остерегайтесь пересечения границ модуля.

Тогда лучше возвращать примитивные типы, поскольку типы C ++ не обязательно бинарно совместимы даже с разными версиями одного и того же компилятора.

4
ответ дан 24 November 2019 в 15:25
поделиться

Если вы передаете указанную строку и работаете с этой строкой, вам не нужно возвращать что-нибудь. ;)

1
ответ дан 24 November 2019 в 15:25
поделиться

I agree with the other posters, that you should use string.

But know, that depending on how aggressively your compiler optimizes temporaries, you will probably have some extra overhead (over using a dynamic array of chars). (Note: The good news is that in C++0a, the judicious use of rvalue references will not require compiler optimizations to buy efficiency here - and programmers will be able to make some additional performance guarantees about their code without relying on the quality of the compiler.)

In your situation, is the extra overhead worth introducing manual memory management? Most reasonable programmers would disagree - but if your application does end up having performance issues, the next step would be to profile your application - thus, if you do introduce complexity, you only do it once you have good evidence that it is needed to improve overall efficiency.

Someone mentioned that Return Value optimization (RVO) is irrelevant here - I disagree.

The standard text (C++03) on this reads (12.2):

[Начало стандартной цитаты]

Временные объекты типа класса создаются в различных контекстах: привязка rvalue к ссылке (8.5.3), возврат rvalue (6.6.3), преобразование, которое создает rvalue (4.1 , 5.2.9, 5.2.11, 5.4), выброс исключения (15.1), вход в обработчик (15.3) и при некоторых инициализациях (8.5). [Примечание: время жизни объектов исключения описано в 15.1. ] Даже когда создание временного объекта избегается (12.8), все семантические ограничения должны соблюдаться, как если бы временный объект был создан. [Пример: даже если конструктор копирования не вызывается, все семантические ограничения, такие как доступность (пункт 11), должны быть выполнены. ]

 [Example:  
struct X {
  X(int);
  X(const X&);
  ˜X();
};

X f(X);

void g()
{
  X a(1);
  X b = f(X(2));
  a = f(a);
}

Здесь реализация может использовать временный объект для создания X (2) перед передачей его в f () с помощью конструктора копирования X; в качестве альтернативы, X (2) может быть построен в пространстве, используемом для хранения аргумента. Кроме того, временный объект может использоваться для хранения результата f (X (2)) перед его копированием в b с помощью конструктора копирования X; в качестве альтернативы результат f () может быть построен в b. С другой стороны, выражение a = f (a) требует временного значения либо для аргумента a, либо для результата f (a), чтобы избежать нежелательного псевдонима а. ]

[End Standard Quote]

По сути, в приведенном выше тексте говорится, что вы можете полагаться на RVO в ситуациях инициализации, но не в ситуациях присваивания. Причина в том, что когда вы инициализируете объект, нет способа, чтобы то, чем вы его инициализируете, могло когда-либо быть наложено на сам объект (вот почему вы никогда не выполняете самопроверку в конструкторе копирования), но когда вы это делаете

В вашем коде нет ничего, что по сути запрещает RVO - но прочтите документацию по компилятору, чтобы убедиться, что вы действительно можете положиться на него, если он вам действительно нужен.

3
ответ дан 24 November 2019 в 15:25
поделиться
Другие вопросы по тегам:

Похожие вопросы: