对释放的内存有一个引用是未定义的行为吗?

问题描述 投票:0回答:1

在C++中,如果释放的内存仍然被一个引用所引用,即使该引用没有被再次使用,这是否是未定义的行为?例如,下面的函数是否调用了未定义的行为?

void foo() {
    std::map<std::string, int> mymap;
    {
        int& val = mymap["eight"];
        val = 8;
        mymap.erase("eight"); // Oops! val still refers to mymap["eight"]
        // val is not used again
    }
    std::cout << "Entry count: " << mymap.size() << "\n";
}
c++ reference language-lawyer lifetime
1个回答
0
投票

从[associative.reqmts]p9中,我们看到(强调是我的)。

insert和emplace成员不应影响到容器的迭代器和引用的有效性,而且... ... erase成员只对被擦除元素的迭代器和引用无效。.

这是N4659[basic.stc]p4中的内容。1 再次强调)。

当一个存储区域的持续时间结束时,代表该存储区域任何部分地址的所有指针值都会变成无效指针值(6.9.2)。通过无效指针值进行引导和将无效指针值传递给deallocation函数的行为是未定义的。. 任何其他用途 的无效指针值具有实现定义的行为。

虽然文中特别谈到了指针,但没有理由相信它不适用于引用(好吧,在某种程度上它们可以被认为是指针)。另外,请注意,它说"Any other use",所以只要在表达式失效后不在表达式中使用指针引用,行为应该是很好定义的。

1 注:看来这段文字是在N4659中添加的,在标准的早期版本中似乎并不存在。


-4
投票

对释放的内存有引用是未定义的行为吗?

标准并没有为 "拥有 "任何类型的值定义任何行为。


mymap.erase("eight"); // Oops! val still refers to mymap["eight"]

以下是标准中关于 erase:

[associative.reqmts].。擦除成员应使被擦除元素的引用无效......。

请注意,这条规则并没有说如果这些引用存在,行为就没有定义。事实上,如果引用的存在总是意味着未定义的行为,那么描述那些引用无效是相当没有意义的。

至于什么是无效引用的定义......标准似乎有所欠缺。无效指针有定义,但我找不到无效引用的定义。这种缺乏定义的情况可以被认为是标准的一个缺陷。

© www.soinside.com 2019 - 2024. All rights reserved.