考虑以下 C++ 代码:
#include <bits/stdc++.h>
template <typename T> void print_type() { std::cout << __PRETTY_FUNCTION__ << std::endl; }
class Base{
int num;
public:
Base() : num{0} {}
friend std::ostream & operator << ( std::ostream& stream, Base & obiekt){
stream<< "num: " << obiekt.num;
return stream;
}
};
int main(){
Base a{};
std::cout << a << std::endl;
std::cout << "type of a: " << std::endl;
print_type < decltype( a ) > ();
std::cout << "type of (a): " << std::endl;
print_type < decltype( (a) ) > ();
Base b();
std::cout << b << std::endl;
std::cout << "type of b: " << std::endl;
print_type < decltype( b ) > ();
std::cout << "type of (b): " << std::endl;
print_type < decltype( (b) ) > ();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我用 g++ 7.2.0 编译它,并得到以下输出:
num: 0
type of a:
void print_type() [with T = Base]
type of (a):
void print_type() [with T = Base&]
1
type of b:
void print_type() [with T = Base()]
type of (b):
void print_type() [with T = Base (&)()]
Run Code Online (Sandbox Code Playgroud)
我的问题:
std::cout << b << std::endl;打印“1”?Base()像or 这样的类型是什么Base (&)()?(a)为什么有类型Base&,什么时候a有类型Base?我正在寻找答案,但找不到。我知道在这种情况下我应该使用不带任何括号的声明Base a;,但我想知道Base a;,Base a{};和之间的区别Base a();。为什么它在没有任何警告或错误的情况下进行复制?感谢帮助。
主要问题是:
Base b();
Run Code Online (Sandbox Code Playgroud)
不按你的想法做。事实上,它是一个函数的声明,该函数接受零个参数并返回一个类型的对象Base。
为什么 std::cout << b << std::endl; 打印“1”?
因为b是一个指向函数的指针。结果,过载:
basic_ostream& operator<<( bool value );
Run Code Online (Sandbox Code Playgroud)
被使用并被1打印为指向函数的指针永远不会为空。
一个更有趣的问题是为什么 gcc 甚至接受代码并且只产生警告。function 没有定义b,只有它的声明,所以我希望代码不会链接。
Base() 或 Base (&)() 等类型是什么?
Base()是一个指向函数的指针,不接受任何参数,并且 return Base,Base (&)()是对同一函数的引用。
为什么 (a) 的类型是 Base&,而 a 的类型是 Base?
因为decltype 这样工作:
decltype(expression)
Run Code Online (Sandbox Code Playgroud)
如果参数是不带括号的id 表达式或不带括号的类成员访问表达式,则 decltype 生成由此表达式命名的实体的类型。如果没有这样的实体,或者参数指定了一组重载函数,则程序的格式不正确。
如果参数是 T 类型的任何其他表达式,并且
a) 如果表达式的值类别是 xvalue,则 decltype 产生 T&&;
b)如果表达式的值类别是左值,则 decltype 产生 T&;
c) 如果表达式的值类别是纯右值,则 decltype 产生 T。