2017-08-17 91 views
10

为什么这个代码有效?与c++14在主函数中声明的C++结构体

// 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

+0

它知道是因为'fun'的返回类型,它被推断为'struct a'。 – nwp

+0

如果我从'auto x ='更改为'a x =',它不会编译,为什么'auto'有效? – PYA

+0

Becouse编译器会在编译时推导出返回的变量,所以他知道它会是'struct a'。如果你使用'a x =',编译器不会知道这个数据类型,因为它在另一个作用域中被声明。 –

回答

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在所有它的荣耀。

as @Barry建议当您从类中返回一个私有类型的实例时会发生同样的情况。所以我们从C++ 03开始就有这种行为。你可以自己尝试。

+0

甚至可以在C++ 03中用返回私有类型的实例来完成同样的事情。 – Barry

+0

另一个例子是lambda表达式,它从来没有名字,但往往只是结构与'运营商()'。 – rustyx

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; 

} 

现在,这里也没关系您是否使用aauto,因为amain()可见。现在auto是一个不同的故事。编译器问:我是否有足够的信息来推断(毫不含糊地)x的类型是什么?答案是肯定的,因为a没有其他选择。

+0

我知道为什么你的代码工作运行它,我只是在考验看到的东西当结构是一个功能,但事实上,'auto'能“猜测”是一种可怕的我:( – PYA

+1

@pyjg“猜测”是一个错误的词。它要么毫无疑问知道或者它给你一个错误有没有猜测参与其中。 – nwp

+0

@pyjg其实对于我来说,这是离奇它无法检测它在C++ 98/03。为什么不呢?有没有在决定型绝对没有歧义,那么为什么要创建一个编译错误?这在C++ 14。 –