使用带有valarray的c ++标准库算法

时间:2011-03-09 01:03:28

标签: c++ stl stl-algorithm

我试图避免重新实现我自己的标准算法的笨拙版本,因此我正在使用标准库版本。由于我不是C ++方面的专家,所以我会谨慎行事并打开完整的调试选项。

具体来说,我在valarray容器上使用二进制搜索。以下代码块似乎产生了正确的结果,valgrind没有抱怨。尽管如此,我确实感觉自己处于一个滑坡上,因为我不确定我所做的事情是否真的被允许,或者我是不是被编译器释放了。

一段代表性的代码:

#include <iostream>
#include <valarray>
#include <algorithm>
#include <typeinfo>

using namespace std;

int main(){

 valarray<double> v(10);
 for (int i=0 ; i<10 ; ++i){
   v[i]=2. *i ; 
   cout<<v[i]<<"  ";
 }
 cout << "\n";

 double what=17;
 double* it=lower_bound(&v[0], &v[10],what) ; 

 cout<<it-&v[0]<<" "<<typeid(&v[0]).name()<<" ";
 cout<<typeid(it).name()<<" "<<typeid(it-&v[0]).name()<<"\n"; // ???

 int idx=it-&v[0];
 cout<<"v["<<idx<<"]="<<v[idx]<<"\n";
}

问题:

  1. 我在这里做的真的合法吗?
  2. 两个指针之间的差异怎么变成一个int? (在???评论的行中)
  3. 类型转换的开销是多少? ---我 am 关注效率,因为这种功能将占用代码的一部分,占用计算时间的90%以上。

3 个答案:

答案 0 :(得分:2)

  1. 您正在使用int索引valarray。这对于这个例子是有效的,但不是一般的。使用std::size_t索引valarray。 (std::vector和普通数组也是如此。)

  2. 指向任何类型的两个指针之间的区别是未指定的整数类型,可能是intlong,并且总是足够小以适合std::ptrdiff_t

  3. 哪种转换?

答案 1 :(得分:1)

我相信这是所有定义的行为,将继续适用于任何实现。查看valarray的各种文档,看起来它必须合法才能使::std::valarray的所有其他内容成立。在调用resize成员函数或销毁valarray之前,指向元素的裸指针应保持完全有效。

唯一真正的问题是,valarray是否需要连续保持其元素。我找到了answer to that question in a post。我会在这里摘录它:

  

是的,valarray也使用连续的   存储。具体措辞来自   标准是($ 26.3.2.3 / 3):   表达&amp; a [i + j] ==&amp; a [i] + j   对于所有size_t我评估为真   size_t j使得i + j小于   非常数数组的长度   一个。

当然,切片仍然无法直接与标准算法一起使用,尽管创建切片迭代器不应该太难。制作一个双向的很容易,但要创建一个随机访问迭代器要困难得多(要完全正确地进行大量的数学操作)。

两个指针之间的区别变成(正如其他人所说)::std::ptrdiff_t。这将是不同平台上的不同类型。我在64位Fedora 14下使用gcc,类型为long。这种'类型转换'没有开销。它甚至不是转换。编译器只进行减法,好像两个指针是普通的旧数字,结果是某个类型的普通旧数字。使用::std::ptrdiff_t作为类型是为了确保所使用的数字类型足够大,以保持系统中任何两个指针之间的差异。

答案 2 :(得分:0)

这些it-&v[0]真的吓到我..你的意思是it->v[0]? lower_bound的返回值是valarray<double>::iterator类型,请使用它而不是double*!所有其他derefencing问题将自动消失。例如,您可以执行*itit++但不能执行it->v[0],因为它不是指针而是迭代器。它很可能是一个v.end() - 迭代器,使你的所有注意力都变得非法。

有关迭代器的更多信息:http://www.cppreference.com/wiki/iterator/start

编辑:哦,现在我明白了,你正在使用可怕的指针运算!那就是C,我们不再这样做了;)

相关问题