'const std :: string&'后面的变量参数列表弄乱堆栈

时间:2017-06-27 14:19:52

标签: c++ c++11 pass-by-reference

我有一个功能:std::string format(const std::string sformat, ...); 它基本上像一个花哨的sprintf()。

由于我调用了很多函数,我想将格式字符串作为ref:const std::string& sformat传递。 不幸的是,va_start()似乎在查找堆栈上的正确位置到变量参数列表时遇到了问题。

如果我删除'&'它工作正常。

两个问题: A:我是否甚至需要引用以防止在调用期间发送sformat副本,或者优化器是否足够聪明才能执行传递-ref在后台? B:我该怎样做才能阻止格式字符串的传值,仍然不会混淆va_start()?

我的猜测是:传递指针。或者有更好的解决方案吗?

1 个答案:

答案 0 :(得分:0)

namespace details {
  std::string format(char const* sformat, ...) {
    // code
  }
}
template<class...Args>
std::string format(std::string const& str, Args const&... args) {
  return details::format( str.data(), args... );
}

作为奖励,我可以写一个to_pod帮助者:

namespace details {
  std::string format(char const* sformat, ...) {
    // code
  }
}
template<class T>
T const& to_pod(T const& t){ return t; }
template<class Char, class Attribs>
Char const* to_pod( std::basic_string<Char, Attribs> const& str ) {
  return t.data();
}
template<class...Args>
std::string format(std::string const& str, Args const&... args) {
  return details::format( str.data(), to_pod(args)... );
}

现在我可以将std::string传递给第一个参数,并将它们自动转换为指向缓冲区的char const*

...

如果您没有C ++ 11编译器(比如MSVC 2010),那么您最好的选择就是编写重载。

std::string format(std::string const& str) {
  return details::format( str.data() );
}
template<class A0>
std::string format(std::string const& str, A0 const& a0) {
  return details::format( str.data(), to_pod(a0) );
}
template<class A0, class A1>
std::string format(std::string const& str, A0 const& a0, A1 const& a1) {
  return details::format( str.data(), to_pod(a0), to_pod(a1) );
}
// etc

你可能不会想要超过10个参数。