如何在c ++

时间:2018-12-30 01:20:50

标签: c++11

我如何获得指向集合中第一个元素的指针

   int main()
   {
    std::vector<int> v ;
    v.insert(v.end() , 1);
    v.insert(v.end() , 2);
    v.insert(v.end() , 5);
    v.insert(v.end() , 4);

    std::set<int> s ;

    s.insert(s.end() , 754);
    s.insert(s.end() , 5);
    s.insert(s.end() , 3);
    s.insert(s.end() , 4);

    std::list<int> l ;

    l.insert(l.end() , 45);
    l.insert(l.end() , 5);
    l.insert(l.end() , 3);
    l.insert(l.end() , 4);

    int *p = (int*)(&*l.begin());  <<<<<<-------- ( here )
    cout << *p++ <<endl;
    cout << *p++ <<endl;
    cout << *p++ <<endl;
    cout << *p <<endl;

它可以与vectors一起使用,但是它给我提供了set和list的垃圾值 任何想法吗?

3 个答案:

答案 0 :(得分:2)

在使用指针算术和容器时要非常小心。 std :: vector使用连续的内存,并且指针将按预期工作。其他容器可能不会在连续内存中存储信息,并且增加指针可能无法遍历该容器。

改为使用迭代器。例如:

std::set<int> s;
//add stuff to the set
auto setit = s.begin(); //setit is an iterator for s
cout << *setit++ << endl;
//etc.

迭代器知道如何遍历容器,并且可以使用与指针类似的方法,尽管有区别。值得阅读有关您计划使用的容器的文档-查找可以使用哪种类型的迭代器,以及哪些操作会使迭代器无效。

例如,阅读documentation for std::set。它描述了可以使用的迭代器类型。在每个修饰符的文档中,它还告诉迭代器是否无效。例如,如果您在集合中使用insert,则迭代器不会无效。

答案 1 :(得分:0)

@rsjaffe是正确的,您应该使用iterator

但是,您正在使用对象。

这些对象有一些责任,即以一定的保证金来存储物品。

含糊:

  • std::vector的项目进行快速读/写访问
  • 自动排序并在插入std::set时保留一个(以及相对较快的插入和检索...)
  • 快速插入/删除std::list

这些类的目标是使这些概念起作用,同时隐藏其内部作用。

从逻辑上讲,您有一个带有漂亮按钮的漂亮遥控器,但是您不知道它们的工作方式,并且制造商不提供任何保证,它将以相同的方式超时工作。您只知道它有效(或者您可以根据需要对其进行测试)。

以同样的方式,Iterators是封装了横向集合事物

std::set中没有指向头部的指针,因为元素不是那样保留的。

从这种角度来看,将std::vector::iterator强制转换为指针的操作是偶然的,而问题是无关紧要。

答案 2 :(得分:0)

因为向量的内存布局是所包含元素类型的连续内存位置,所以创建的指针是普通的C指针。

对于集合和列表,包含的元素是结构的一部分。对于列表,可能是这样的:

struct list {
  int value;
  struct list *next;
}

struct list {
  struct list *next;
  int value;
}

看起来非常像C,没有模板和方法。因此,当您使用结构体的地址时,您可以读取该值或下一个指针,但是当将指针增加到int时,如果还没有该指针,则会得到一个垃圾值。

在设置和列出的情况下,它甚至不能帮助您拥有正确的指针类型,即。指向结构列表的指针,因为它们在内存中不连续,因此增加它们将无法获得正确的值。