离开作用域后为什么仍然有效访问struct?

时间:2014-01-07 07:54:17

标签: c++ operator-overloading destructor

首先,我想了解为什么我在输出中得到第(5)和(6)行,而不仅仅是其中之一。 第二,为什么mc1.print()打印有效值?不应该_ms指向mc1(&MyStruct(mc2))之后的未定义位置,因为创建MyStruct的位置(在强制转换操作符中)已经放松了吗?

struct MyStruct
{
    int w;
    int h;

    MyStruct()
    {
        cout << "MyStruct" << endl;
    }
    ~MyStruct()
    {
        cout << "~MyStruct: w=" << w << "h=" << h << endl;;
    }
};

class MyClass1
{
public:
    MyClass1(MyStruct* ms)
        :_ms(ms)
    {
        cout << "MyClass1" << endl;;
    }
    ~MyClass1()
    {
        cout << "~MyClass1" << endl;
    }

    void print()
    {
        cout << "print: w=" << _ms->w << "h=" << _ms->h << endl;
    }

    MyStruct* _ms;
};

class MyClass2
{
public:
    MyClass2()
    {
        cout << "MyClass2" << endl;
    }
    ~MyClass2()
    {
        cout << "~MyClass2" << endl;
    }

    operator MyStruct()
    {
        MyStruct ms;
        ms.h = 11;
        ms.w = 22;;
        return ms;
    }
};

int main()
{
    MyClass2 mc2;   
    MyClass1 mc1(&MyStruct(mc2));

    mc1.print();

    return 0;
}

输出

1.    MyClass2
2.    MyStruct
3.   ~MyStruct: w=22h=11
4.    MyClass1
5.    ~MyStruct: w=22h=11
6.    ~MyStruct: w=22h=11
7.    print: w=22h=11

2 个答案:

答案 0 :(得分:2)

  

为什么在离开范围后仍然有效访问struct?

没有。它不是有效。您可以尝试读取任意内存地址,但这样做无效“.C ++标准只是没有说明如果您执行”无效“操作会发生什么。所以您的代码可以执行您正在观察的内容。< / p>

答案 1 :(得分:1)

  

首先,我想了解为什么我在输出中得到第(5)和(6)行,而不仅仅是其中之一。

我不知道。 I don't,但由于该程序具有未定义的行为,原则上任何事情都可能发生。

  

其次,为什么mc1.print()打印有效值?

没有。它通过打印曾经被死时临时占用的内存中的任何内容来提供未定义的行为,如果该内存仍然可访问的话。在你的情况下,只是没有任何东西被重用或以其他方式使内存失效,所以你碰巧看到你在临时活着时放在那里的值。

  

_ms之后不应该mc1(&MyStruct(mc2))指向未定义的位置,因为创建MyStruct的位置(在演员中)已经放松了吗?

它指向一些不再包含有效对象的内存位置。通常,在函数返回之前不会释放堆栈帧。即使它存在,内存通常仍然可访问。因此,访问一个死对象会给你一些未定义的行为,这可能不是你认为它应该给出的任何未定义的行为。