不完全是一个问题,虽然只是我一直在思考如何通过风格更优雅地编写这样的代码,同时充分利用新的c ++标准等。这是一个例子
将Fibonacci序列返回到一个容器,最多N个值(对于那些在数学上不倾斜的序列,这只是添加前两个值,前两个值等于1.即1,1,2,3,5,8,13 ,...)
示例从main运行:
std::vector<double> vec;
running_fibonacci_seq(vec,30000000);
1)
template <typename T, typename INT_TYPE>
void running_fibonacci_seq(T& coll, const INT_TYPE& N)
{
coll.resize(N);
coll[0] = 1;
if (N>1) {
coll[1] = 1;
for (auto pos = coll.begin()+2;
pos != coll.end();
++pos)
{
*pos = *(pos-1) + *(pos-2);
}
}
}
2)相同但使用 rvalue &amp;&amp;而不是&amp; 1.E。
void running_fibonacci_seq(T&& coll, const INT_TYPE& N)
编辑:正如下面评论过的用户所注意到的那样,右值和左值在时间上没有任何作用 - 由于评论中讨论的原因,速度实际上是相同的
结果N = 30,000,000
Time taken for &:919.053ms
Time taken for &&: 800.046ms
首先我知道这不是一个问题,但这些或哪个是最好的现代c ++代码?使用右值参考(&amp;&amp;),似乎移动语义就位,并且没有不必要的副本,这使得时间有了很小的改进(对于我来说,由于未来的实时应用程序开发很重要)。一些特定的“问题”是
a)将一个容器(在我的例子中是向量)传递给函数作为参数并不是关于如何真正使用rvalue的优雅解决方案。这个事实是真的吗?如果是这样,在上面的例子中rvalue如何显示它的亮点?
b) coll.resize(N); 调用和 N = 1 的情况,有没有办法避免这些调用,因此给用户一个简单的界面只使用该函数而不动态创建向量的大小。模板元编程是否可以在这里使用,因此向量在编译时分配了特定的大小? (即running_fibonacci_seq&lt; 30000000&gt;)因为数字可能很大,是否需要使用模板元编程,如果可以,我们也可以使用this (link)
c)有更优雅的方法吗?我有一种感觉std :: transform功能可以通过使用 lambdas 来使用,例如。
void running_fibonacci_seq(T&& coll, const INT_TYPE& N)
{
coll.resize(N);
coll[0] = 1;
coll[1] = 1;
std::transform (coll.begin()+2,
coll.end(), // source
coll.begin(), // destination
[????](????) { // lambda as function object
return ????????;
});
}
[1] http://cpptruths.blogspot.co.uk/2011/07/want-speed-use-constexpr-meta.html
答案 0 :(得分:2)
明显的答案:
std::vector<double> running_fibonacci_seq(uint32_t N);
为什么?
因为常数:
std::vector<double> const result = running_fibonacci_seq(....);
因为不变量更容易:
void running_fibonacci_seq(std::vector<double>& t, uint32_t N) {
// Oh, forgot to clear "t"!
t.push_back(1);
...
}
但速度是多少?
有一种称为返回值优化的优化,允许编译器在许多情况下省略副本(并直接在调用者的变量中构建结果)。即使复制/移动构造函数具有副作用,C ++标准也明确允许它。
那么,为什么要传递“out”参数?
t
的内存缓冲区)答案 1 :(得分:2)
由于“引用折叠”,此代码不使用右值引用,也不会移动任何内容:
template <typename T, typename INT_TYPE>
void running_fibonacci_seq(T&& coll, const INT_TYPE& N);
running_fibonacci_seq(vec,30000000);
当你认识到这一点时,你的所有问题(以及现有的评论)都变得毫无意义。
答案 2 :(得分:1)
简介:
#include <vector>
#include <cstddef>
#include <type_traits>
template <typename Container>
Container generate_fibbonacci_sequence(std::size_t N)
{
Container coll;
coll.resize(N);
coll[0] = 1;
if (N>1) {
coll[1] = 1;
for (auto pos = coll.begin()+2;
pos != coll.end();
++pos)
{
*pos = *(pos-1) + *(pos-2);
}
}
return coll;
}
struct fibbo_maker {
std::size_t N;
fibbo_maker(std::size_t n):N(n) {}
template<typename Container>
operator Container() const {
typedef typename std::remove_reference<Container>::type NRContainer;
typedef typename std::decay<NRContainer>::type VContainer;
return generate_fibbonacci_sequence<VContainer>(N);
}
};
fibbo_maker make_fibbonacci_sequence( std::size_t N ) {
return fibbo_maker(N);
}
int main() {
std::vector<double> tmp = make_fibbonacci_sequence(30000000);
}
fibbo_maker
的东西只是我聪明。但它让我可以推断出你想要的纤维序列的类型,而不必重复它。