简体   繁体   English

这个std :: cout最终会输出垃圾还是意外的东西吗?

[英]Will this std::cout eventually print garbage or something unexpected?

Take a look at this code. 看一下这段代码。

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;
}

This simple code prints 2 in both cases, but I'm not sure if this would be the behaviour for every possible execution. 在两种情况下,此简单代码都将输出2 ,但是我不确定这是否是每次可能执行的行为。

Since the vector is at one point reallocating (well, not necessarily always, that depends on the segment management decisions by the OS), shouldn't this print fail at one point? 由于矢量是在某一时刻重新分配的(嗯,不一定总是,这取决于操作系统的段管理决定),这种打印是否应该在某一时刻失败?

I printed the pointers using printf and %p at different points and the values were different, but I don't fully understand the behaviour of C++'s true references; 我在不同的位置使用printf%p打印了指针,并且值不同,但是我不完全了解C ++的真实引用的行为。 is it always safe to do this? 这样做总是安全吗? (make a C++ reference to something that might change it's memory position) (对可能更改其内存位置的内容进行C ++引用)

Your program has undefined behavior. 您的程序具有未定义的行为。

ref and ref_bad are invalidated when push_back() is called on v . v上调用push_back()时, refref_bad无效。

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

If the new size() is greater than capacity() then all iterators and references (including the past-the-end iterator) are invalidated. 如果新的size()大于capacity()则所有迭代器和引用(包括过去的迭代器)都将失效。 Otherwise only the past-the-end iterator is invalidated. 否则,只有过去的迭代器是无效的。

Despite what somebody may say, references are actually syntactic sugar for pointers in disguise, there's exactly zero magic about them 1 . 尽管有人可能会说,引用实际上是变相指针的语法糖,关于它们的魔力完全为零1

Knowing this, it's clear that, if you keep a pointer (=reference) to memory that gets reallocated, such a pointer (=reference) becomes invalid, as it points to memory you no longer own, thus accessing it is Undefined Behavior. 知道这一点,很明显,如果您保留指向已重新分配的内存的指针(= reference),则该指针(= reference)变得无效,因为它指向您不再拥有的内存,因此访问它是未定义行为。

Notice that, for STL containers, this is all documented - if you look up std::vector<T>::push_back you'll find that, if the new size becomes greater than the current capacity, it can invalidate all iterators and references. 请注意,对于STL容器,所有内容都已记录在案-如果您查找std::vector<T>::push_back您会发现,如果新大小超过当前容量,它将使所有迭代器和引用无效。

That's the reason why generally when you manipulate vectors you keep indexes, not iterators or pointers. 这就是为什么通常在操作向量时保留索引而不是迭代器或指针的原因。


  1. The only magic of references that I can think of is that const references can bind to tenporaries and keep them alive beyond the end of the original expression (subjected to some rules). 我能想到的唯一的引用魔术就是, const引用可以绑定到tenporaries,并使它们保持原始表达式末尾(受某些规则约束)之外的状态。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM