在函数中声明的C ++结构在main中可见

时间:2017-08-17 14:34:45

标签: c++ c++14

为什么这段代码有效?与c++14

// Example program
#include <iostream>
#include <string>
using namespace std;


auto fun()
{
    struct a
    {
        int num = 10;
        a()
        {

            cout << "a made\n";
        }
        ~a()
        {
            cout << "a destroyed\n";
        }
    };
    static a a_obj;
    return a_obj;
}


int main()
{
    auto x = fun();
    cout << x.num << endl;

}

主要的a类型如何?如果我将auto x=更改为a x=,它显然无法编译,但主要知道类型a如何?

static声明就在那里,因为我试图测试其他东西,但后来我偶然发现了这种行为。

在此处运行:https://wandbox.org/permlink/rEZipLVpcZt7zm4j

2 个答案:

答案 0 :(得分:12)

在您意识到这一点之前,这一切都令人惊讶:名称可见性不会隐藏类型。它只是隐藏了类型的名称。一旦你理解了这一切,这一切都是有道理的。

我可以在没有auto的情况下向您展示,只使用普通的旧模板:

auto fun()
{
    struct Hidden { int a; };

    return Hidden{24};
}

template <class T> auto fun2(T param)
{
    cout << param.a << endl; // OK
} 

auto test()
{
    fun2(fun()); // OK
}

如果你仔细观察,你会发现这与你的情况相同:

你有Hidden的本地结构fun。然后在Hidden内使用test类型的对象:调用fun,返回Hidden obj,然后将此对象传递给fun2转而完全没有问题可以使用对象Hidden来实现它的荣耀。

因为@Barry建议在从类中返回私有类型的实例时会发生同样的事情。所以我们从C ++ 03开始就有这种行为。你可以亲自试试。

答案 1 :(得分:1)

C ++ 14对auto的容忍度越来越高。你的问题不明确,因为你没有说明问题所在。

现在让我们以不同的方式解决您的问题:为什么它不适用于a x = ...

原因是struct定义不在main的范围内。现在这可行:

// Example program
#include <iostream>
#include <string>
using namespace std;

struct a
{
    int num = 10;
};

auto fun()
{
    static a a_obj;
    return a_obj;
}


int main()
{
    a x = fun();
    cout << x.num << endl;

}

现在,无论您使用a还是auto都无关紧要,因为amain()可见。现在auto是另一回事。编译器问:我是否有足够的信息来推断(明确地)x的类型是什么?答案是肯定的,因为除a之外别无选择。