繁体   English   中英

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

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

看一下这段代码。

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 ++引用)

您的程序具有未定义的行为。

v上调用push_back()时, refref_bad无效。

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

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

尽管有人可能会说,引用实际上是变相指针的语法糖,关于它们的魔力完全为零1

知道这一点,很明显,如果您保留指向已重新分配的内存的指针(= reference),则该指针(= reference)变得无效,因为它指向您不再拥有的内存,因此访问它是未定义行为。

请注意,对于STL容器,所有内容都已记录在案-如果您查找std::vector<T>::push_back您会发现,如果新大小超过当前容量,它将使所有迭代器和引用无效。

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


  1. 我能想到的唯一的引用魔术就是, const引用可以绑定到tenporaries,并使它们保持原始表达式末尾(受某些规则约束)之外的状态。

暂无
暂无

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

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