【问题标题】:Reference class member (was) causing undefined behavior引用类成员 (was) 导致未定义的行为
【发布时间】:2015-03-29 04:49:12
【问题描述】:

我正在尝试创建一个包含另一个类作为引用(私有成员)的类。

class example{
private:
    std::vector<char> chars;
};

class example2{
    example2(example to_be_initialized) :ref(to_be_initialized) { }
private:
    example& ref;
};

希望缺少细节不会让任何人感到困扰(我知道你们喜欢看完整的代码,但我减少了它,因为如果这不是问题,那是我必须弄清楚的其他问题。但我会发布更多/其余的(如果需要),但我的代码与此非常相似,在做任何涉及 ref 的事情时我会得到奇怪的 unicode 字符。一旦我将 ref 更改为非引用,所有奇怪的未定义行为都消失了。

我想知道以上内容是否合法,仅供将来参考。我知道在这种情况下我不会通过引用类来节省大量内存(因为它只是复制指针,对吗?),但我觉得将来有必要这样做。

提前致谢。

【问题讨论】:

    标签: c++ class reference initialization


    【解决方案1】:

    代码有一个主要问题:构造函数通过值获取其参数,这意味着引用指向一个临时对象。在构造函数调用之后,它作为悬空引用留下。

    您需要从有效对象初始化引用。您可以通过将构造函数参数设为引用来做到这一点:

    class example2
    {
    public:
        example2(example& to_be_initialized) : ref(to_be_initialized) { }
    
    private:
        example& ref;
    };
    

    然后

    example e;
    example2 e2(e); // e2.ref and e are the same object
    

    注意:您必须确保您了解引用的语义才能使用它。引用并不真正“像指针”。它是一个且唯一一个现有对象的别名。除非你真的需要引用语义,否则你应该存储一个对象:

    class example2
    {
    public:
        example2(const example& to_be_initialized) : ex(to_be_initialized) { }
    
    private:
        example ex;
    };
    

    【讨论】:

    • 哇哦,非常感谢!我不敢相信我没有抓住这一点,而且我的程序有时“工作”,即使有一个悬空的参考。不幸的是,引用类确实有我需要调用的函数,所以我不能让它成为一个常量,但我将来肯定会记住这一点,因为我从来没有这样想过。再次感谢您的详细回复:)(希望我没有在上面做出任何错误的假设)
    • @cjh418 我不认为我说过要让它成为一个常数,不管“它”是什么。这也与调用函数没有太大关系。
    • 哦,你是对的,我误解了你的例子,将“ex”(从你的最后一个例子)更改为一个常量。我现在明白了,除非我需要在构造函数中修改它,否则参数是常量。
    • 实际上,您的示例甚至不会以这种方式编译(从 const ex 类型的表达式中对 ex& 类型的无效初始化),我想这就是为什么我假设您在谈论更改私有成员 ex(再次,参考你的最后一个例子)到一个常量。
    • @cjh418 一旦构造函数被公开,它们都会编译(假设它已编译,我愚蠢地从您损坏的示例中剪切并粘贴。)请参阅herehere。你显然做错了什么。
    猜你喜欢
    • 2021-11-30
    • 2021-01-26
    • 2021-07-10
    相关资源
    最近更新 更多