5

随着返回值优化之上的右值引用的出现,实现这样的核心功能的最有效方法是什么?我该如何改进这个实现,或者我应该不理会它?

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

显然,如果可以的话,我想避免复制或分配内存。TIA。

编辑:感谢 D. Rodriguez 提供详细的答案。现在,我的问题有第二部分。有没有办法改善这一点?

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

当然,如果可以的话,我想避免使用 MACRO,但是如果我复制并粘贴上面的模板代码以返回 ss.str().c_str() 和 const char*,则临时文件的寿命不够长;尽管代码似乎可以运行,但 valgrind 抱怨(红灯)。

对于 to_cstr(),我无法想出比上面的 MACRO 更清洁的解决方案。任何想法如何改进,或者我也应该不理会?

4

2 回答 2

7

不用管它,它是有效的。即使使用 C++03 编译器,编译器也会优化副本。

基本上,编译器会确保调用代码中的对象to_string、返回语句to_string和返回语句ss.str()都占用完全相同的内存位置。这反过来意味着不会有副本。

在标准规定之外,函数的 return 语句的调用约定按值返回一个对象,该对象不适合我所知道的所有 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`
}
于 2011-10-03T13:07:42.927 回答
0

现在,我的问题有第二部分。有没有办法改善这一点?

#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));
}
于 2011-10-03T14:18:59.283 回答