这个std :: cout最终会打印垃圾还是意外的东西?

时间:2017-04-19 05:14:05

标签: c++ pointers

看看这段代码。

class Obj{
public:
    int id;
    Obj(int id) : id(id){}
};

int main()
{

    std::vector<Obj> v;

    for(int i=0; i<3; i++) // add some elements
        v.push_back(Obj(i));

    Obj& ref = v[2]; // grab references (two ways)
    Obj* ref_bad = &v[2];

    for(int i=3; i<100000; i++) // make the vector re-allocate
        v.push_back(Obj(i));

    std::cout << ref.id << std::endl; // prints 2

    std::cout << (*ref_bad).id << std::endl; // prints 2, but always?

    return 0;
}

在这两种情况下,这个简单的代码打印2,但我不确定这是否是每次可能执行的行为。

由于向量在某一点重新分配(好吧,不一定总是,这取决于操作系统的段管理决策),这个打印不应该在某一点失败吗?

我在不同点使用printf%p打印指针,但值不同,但我并不完全理解C ++真正引用的行为;这样做总是安全的吗? (对可能改变其内存位置的内容进行C ++引用)

2 个答案:

答案 0 :(得分:3)

您的程序有不确定的行为。

ref上调用ref_bad时,

push_back()v无效。

来自http://en.cppreference.com/w/cpp/container/vector/push_back

  

如果新size()大于capacity(),则所有迭代器和引用(包括过去的迭代器)都将失效。否则只有过去的迭代器无效。

答案 1 :(得分:2)

尽管有人可能会说,引用实际上是伪装指针的语法糖,但对于它们 1 ,它们完全没有魔力。

知道了这一点,很明显,如果你将指针(=引用)保留到重新分配的内存中,这样的指针(=引用)就会变得无效,因为它指向你不再拥有的内存,因此访问它是Undefined Behavior。

请注意,对于STL容器,这都是记录的 - 如果您查找std::vector<T>::push_back,您会发现,如果新大小变得大于当前容量,它可能会使所有迭代器和引用无效。

这就是为什么通常在操作向量时保留索引,而不是迭代器或指针的原因。

  1. 我能想到的唯一的参考魔法是const引用可以绑定到tenporaries并使它们保持活动超出原始表达式的末尾(受某些规则约束)。