首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >G++-11销毁顺序由G++9改变

G++-11销毁顺序由G++9改变
EN

Stack Overflow用户
提问于 2021-06-21 13:18:12
回答 2查看 159关注 0票数 4

我们有下面的代码( ofc更复杂,我试着做一个最小的例子)。

代码语言:javascript
复制
#include <iostream>
#include <vector>
#include <string>
#include <memory>

template<typename T>
struct use_type
{
    use_type(T& v) : value(v) {}
    T& value;
};

template<typename T>
use_type<T> use(T& value) { return use_type<T>(value); }

template<typename T>
use_type<T> use(const T& value) { return use_type<T>(const_cast<T&>(value)); }

template<typename T>
struct printer_helper
{
    void use(const use_type<T>& use) { uses.push_back(use); }
    void final_action()
    {
        for (const auto& use : uses)
        {
            std::cout << use.value.size() << std::endl;
            for (const auto& v : use.value)
            {
                std::cout << v << ",";
            }
            std::cout << std::endl;
        }
    }
    std::vector<use_type<T>> uses;
};

template<typename T>                                        
struct printer
{
    printer() { helper = new printer_helper<T>(); }
    printer<T>& operator , (const use_type<T>& t)
    {
        helper->use(t);
        return *this;
    }
    ~printer()
    {
        helper->final_action();
        delete helper;
    }
    printer(const printer&) = delete;
    printer& operator =(const printer&) = delete;
    printer(printer&&) = default;
    printer& operator =(printer&&) = default;
    printer_helper<T>* helper;
};

template<typename T>
struct printer_creator
{
    printer<T> operator << (const char*) { return {}; }
};

int main()
{
    using vec = std::vector<std::string>;
    {
    /*vec v1{"abc", "bcd"};
    vec v2{"new", "old", "real"};*/
    printer_creator<vec> p;
    p << "", use(vec{"abc", "bcd"}), use(vec{"new", "old", "real"});
    //p << p, use(v1), use(v2);
    }
}

这段代码在g++-11之前的g++上运行得非常好。对于g++-11,它要么是段错误,要么是输出中的垃圾。是UB吗?如果是的话,你也许可以告诉我,gcc的变化会使它失败,如果可能的话,还会引用标准的话?

活生生的例子:

g++-10 g++-11

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2021-06-21 13:53:40

在……里面

代码语言:javascript
复制
p << "", use(vec{"abc", "bcd"}), use(vec{"new", "old", "real"});

你创造了3个临时成员

  • printer<vec> (来自p << "")
  • vec{"abc", "bcd"}
  • vec{"new", "old", "real"}

它们之间没有顺序(见下面的注释),因此它们可以按任何顺序创建。

只有从左到右的破坏是正确的(所以从右到左的构造),其他顺序将使用悬挂参考和UB。既然你没有秩序保证..。

注意:

我们由于超载operator &&/operator ||而失去短路,

由于重载operator,,我们失去了从左到右的评估顺序。

票数 5
EN

Stack Overflow用户

发布于 2021-06-21 13:33:55

临时向量在创建它们的行的末尾被破坏。p在其作用域的末尾(即向量之后)被破坏。由于p的析构函数使用对现在悬挂的向量的引用,所以代码具有未定义的行为。

如果它曾经工作过,那是纯粹的“运气”,向量析构函数使向量处于可用状态。

票数 10
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/68068670

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档