2

我有两个班级,Foo 和 Bar。Bar 维护对 Foo 的引用,并具有调用 Foo 中的方法来更改其状态的方法。代码如下所示。

class Foo
{
private:
    double m_value;

public:
    void setValue(double value) { 
        this->m_value = value;
    };

    double getValue() {
        return this->m_value;
    };
};

class Bar
{
private:
    Foo& m_foo;

public:
    Bar() : m_foo(Foo()) {
    };

    void setFooValue(double value) {
        m_foo.setValue(value);
    };

    double getFooValue() {
        return m_foo.getValue();
    };
};    

当我在设置后尝试访问 foo 的值时出现问题,如下所示:

Bar bar;

bar.setFooValue(10000.0);

double value = bar.getFooValue();

std::cout << "Foo value is: " << value << std::endl;

哪个输出Foo value is -9.25596e+061。看来内存已损坏 - 为什么?我知道不将 m_foo 存储为参考(即使用Foo m_foo;)将解决问题,但是我也不明白为什么会这样。

更令人费解的是,上面的代码在发布模式下运行时可以正常工作。

我正在使用 Visual Studio 2010 进行编译。

提前谢谢了!

4

3 回答 3

2

很少有编译器会报告构造函数 Bar() 的错误。我在编译时遇到以下错误,

在构造函数“Bar::Bar()”中:由于 -Wfatal-errors 导致“Foo”类型的临时编译终止的“Foo&”类型的非常量引用的无效初始化

Bar() : m_foo(Foo()) { };

在构造函数 Bar 中, Foo() 返回一个在堆栈中创建的对象,当构造函数返回时,它的生命周期结束。因此它的生命周期是暂时的,这将导致访问未定义的内存或悬空引用。

解决方案 1:按原样使用 Foo 对象,无需任何引用

class Bar
{
private:
   Foo m_foo;

public:
   Bar(){
};

void setFooValue(double value) {
    m_foo.setValue(value);
};

double getFooValue() {
    return m_foo.getValue();
};
};    

解决方案 2:将 Foo 对象作为参数传递给 Bar 构造函数,这将在 main 范围内保持有效。

class Bar
{
private:
    Foo &m_foo;

public:
    Bar(Foo &x) : m_foo(x) {
};

void setFooValue(double value) {
    m_foo.setValue(value);
};

double getFooValue() {
    return m_foo.getValue();
};
};    

int main()
{
Foo x;
Bar bar(x);

bar.setFooValue(10000.0);

double value = bar.getFooValue();

std::cout << "Foo value is: " << value << std::endl;
}
于 2013-04-12T10:07:00.213 回答
1

当你创建酒吧

Bar() : m_foo(Foo()) {
};

您提供对新创建的 foo 实例的引用,该实例将超出范围并在分配给 m_foo 后立即被删除。这实际上是 VS c 编译器缺陷,因为 g++ 会给您和此类代码错误,您可以在此处看到。 http://liveworkspace.org/code/3kW04t $218

于 2013-04-12T09:45:27.043 回答
1
Bar() : m_foo(Foo())

您正在尝试从lvalue-reference初始化temporary。你不应该做这样的事情。在最后一个括号之后 - 对象将被销毁,您将有悬空引用。确实,MSVC 中有一个非标准的扩展,它允许绑定临时对象来引用。例如 gcc在此处为此类案例测试给出错误您也可以检查此答案rvalue to lvalue conversion Visual Studio

于 2013-04-12T09:42:31.907 回答