我非常关注代码的性能和可读性,我从Google的Chandler Carruth那里得到了我的大部分想法.我想在不丢失性能的情况下为C++应用以下规则来实现干净的代码.
这样,功能没有副作用.这是代码可读性的必要条件,并使C++成为一种功能.现在来了表现.如果你想编写一个为std :: vector的每个元素添加1的函数,你能做什么?这是我的解决方案.
std::vector<int> add_one(std::vector<int> v) {
for (std::size_t k = 0; k < v.size(); ++k) {
v[k] += 1;
}
return v;
}
...
v = add_one(std::move(v));
...
Run Code Online (Sandbox Code Playgroud)
我发现这非常优雅,只有2个动作.这是我的问题:
PS:人们问我为什么不喜欢通过参考.我有两个参数:
1 - 它没有在调用站点明确指出哪个参数可能会发生变异.
2 - 它有时会扼杀性能.由于别名,引用和指针是编译器的地狱.我们来看下面的代码
std::array<double, 2> fval(const std::array<double, 2>& v) {
std::array<double, 2> ans;
ans[0] = cos(v[0] + v[1]);
ans[1] = sin(v[0] + v[1]);
return ans;
}
Run Code Online (Sandbox Code Playgroud)
将ans作为参考的相同代码慢了2倍:
std::array<double, 2> fref(const std::array<double, 2>& v,
std::array<double, 2>& ans) {
ans[0] = cos(v[0] + v[1]);
ans[1] = sin(v[0] + v[1]);
}
Run Code Online (Sandbox Code Playgroud)
指针别名可防止编译器使用单个机器指令计算sin和cos(Gcc目前不进行优化,但icpc使用值语义进行优化).
对我来说,它似乎是合法的 C++11。缺点可能是基于意见的,所以我不会解决这个问题,但至于你的第三点,编译器只有在可以证明该函数不会以v
任何方式别名的情况下才能进行该转换。由于这样的编译器编写者可能不会选择对简单情况实现这样的优化,他们可以分析并将这种负担(无别名)留给程序员。
但也要考虑:当函数拒绝以具有明显性能特征的清晰版本编写时,也许您正在编写错误的函数。相反,编写一个像标准库一样在一定范围内运行的算法,问题就会消失:
template <typename Iterator>
void add_one(Iterator first, Iterator last)
{
for(; first != last; ++first)
{
(*first) += 1;
}
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
505 次 |
最近记录: |