Каков наиболее эффективный способ реализовать возвращаемое вычисленное значение в C ++? - PullRequest
5 голосов
/ 03 октября 2011

С появлением ссылок на rvalue в верхней части Оптимизации возвращаемого значения, что будет наиболее эффективным способом реализации такой основной функции? Как я могу улучшить эту реализацию или я должен оставить ее в покое?

template <typename T>
string
to_string(const T& t)
{ 
  stringstream ss;
  ss << t;  
  return ss.str();
} 

Очевидно, я хочу избежать копирования или выделения памяти, если смогу. ТИА.

Редактировать: Спасибо Д. Родригесу за этот подробный ответ. Теперь у меня есть вторая часть моего вопроса. Есть ли способ улучшить это?

#define to_cstr( T ) (to_string( T ).c_str())

Конечно, я хотел бы избежать MACRO, если смогу, но если я скопирую и вставлю приведенный выше код шаблона, чтобы вернуть ss.str (). C_str () и const char *, временное хранилище не будет работать достаточно долго; хотя кажется, что код работает, valgrind жалуется (красный свет).

Я не смог придумать более чистого решения, чем MACRO выше для to_cstr (). Любые идеи, как улучшить, или я тоже должен оставить в покое?

  • Ken

Ответы [ 2 ]

7 голосов
/ 03 октября 2011

Просто оставь это в покое, это эффективно, как есть.Даже с компиляторами C ++ 03 компилятор оптимизирует копии.

По сути, компилятор должен убедиться, что объект в вызывающем коде to_string, оператор возврата to_string и оператор возврата ss.str() все занимают одинаковое место в памяти.Что, в свою очередь, означает, что копий не будет.

За пределами того, что предписывает стандарт, соглашения о вызовах для оператора возврата функции, которая возвращает по значению объект, который не подходитв регистрах всех известных мне 32/64 компиляторов (включая VS, gcc, intel, suncc) передается указатель на место в памяти, где функция должна создать возвращаемый объект, так что код будет внутренне преобразован во что-то встроки:

// Not valid C++! Just for illustration purposes
template <typename T>
to_string( uninitialized<string>* res, const T& t ) {
   stringstream ss;
   ss << t;
   stringstream::str( res, &ss ); // first argument is return location
                                  // second argument is `this`
}
0 голосов
/ 03 октября 2011

Теперь у меня есть вторая часть к моему вопросу.Есть ли способ улучшить это?

#define to_cstr( T ) (to_string( T ).c_str())

Конечно, я бы хотел избежать MACRO, если смогу, но если я скопирую и вставлю код шаблона выше, чтобы вернуть ss.str (). c_str () и const char *, временный объект не живет достаточно долго;хотя кажется, что код работает, valgrind жалуется (красный свет).

Вы можете заставить компилятор создать временное значение в области вызова, чтобы временное время жизни соответствовало выражению выражениягде временный создается.Вот как это сделать:

struct TmpStr {
    mutable std::string s;
};

template<typename T>
char const* to_cstr(T value, TmpStr const& tmp = TmpStr()) {
    tmp.s = to_string(value); // your original function
    return tmp.s.c_str(); // tmp lives in the scope of the caller
}

int main() {
    printf("%s\n", to_cstr(1));
}
...