extern const默认构造的对象
extern const default constructed object
这是我的代码
#include <iostream>
using namespace std;
class Q
{
public:
Q() { cout << "constructor" << endl; }
};
extern const Q t/*()*/; //A
const Q s/*()*/; //B
int main()
{
const Q t/*()*/;
}
我希望标记为"A"的行表示我正在创建一个Q类型的对象t,它的链接是外部的,并且它的字段不能修改。创建是由我提供的没有参数的构造函数完成的。
在main中,我希望以同样的方式创建Q类型的本地t对象,尽管它的链接必然只是这个文件,而且事实上,它的范围和持续时间只针对main。
C++允许我在常量Q t/()/中放入或不放入括号;总的来说。在全局范围中,在A行中,我可以放括号,也可以不放括号,构造函数也不会被调用。
在B行中,我只允许不放括号,否则,如果我定义函数原型,编译器会感到困惑。
我的问题是:
考虑到在第//B行不存在这种灵活性,为什么允许我灵活地将()或不放在第//A行?
不管我在1.中的选择如何,我发现"构造函数"不是按A行打印的,尽管它是按B行打印的。为什么?我对此并没有什么期望。一方面,打印它是合理的,因为我们主要看到C++理解调用0参数构造函数,即使没有括号。另一方面,如果是这种情况,那么我将如何对类类型进行非定义声明?
带有extern
关键字的对象声明不是定义,除非它包含显式初始值设定项。您尝试使用()
来强制定义是朝着正确方向迈出的一步。然而,它失败了,因为()
的这种声明会产生语法歧义,这种歧义的解决有利于函数声明,而不是对象声明。
这同样适用于你的所有声明,而不仅仅是你似乎相信的B。我不清楚你为什么声称B行"不存在这种灵活性":你可以在B行中包含()
,也可以省略它。无论哪种情况,声明都是完全有效的,除了()
会声明一个函数。(也就是说,这不仅仅是一种"灵活性",而是一种非常剧烈的质的变化。)
对于B行,问题实际上不存在,因为B行不使用extern
关键字。如果没有extern
,则无论是否使用显式初始值设定项,B行都是对象定义。在您的情况下,保持原样(没有()
)仍然会触发默认构造,就像您想要的那样。这同样适用于main
中的本地声明。
另一方面,行A是有问题的,因为为了强制定义,你需要一个显式的初始值设定项,但()
并没有做你想做的事
为了在"经典"C++98中解决这个问题,您将被迫使用
extern const Q t = Q();
语法,以确保您正在创建由默认构造函数初始化的对象定义。(从教学角度讲,它实际上是默认构造,然后是复制构造,但这是我们在C++98中不得不面对的问题)。
在现代C++(C++11及更高版本)中,您可以使用{}
初始值设定项将其定义为一个定义(具有默认构造)
extern const Q t{};
或
extern const Q t = {};
由于显而易见的原因,基于{}
的语法不会在函数声明中产生任何歧义。
- 被解释为低级别const的const对象的地址
- 使用共享指针的函数调用,其对象应为 const
- 如何从构造函数副本 T(const T&)调用对象 T?
- 在 C++ 中声明 const 对象需要用户定义的默认构造函数.如果我有一个可变成员变量,为什么不呢?
- Google Or-Tools Glop:如何创建指向 const 对象的指针数组?
- 无法使用类型 'const char *' 的左值初始化类型 'char *' 的成员子对象
- 我们可以有一个 setter 成员函数作为从 const 对象引用的 const 吗?
- "this"指向的对象是否与 const 对象相同?
- const auto & 和 auto & if reference 对象之间的区别是 const
- 将对象传递给函数而不将其包装到 std::ref 中,而参数被指定为 const 引用
- C++ - 确定 const char* 是指向字符串文本对象还是动态对象
- 为什么 const YAML::Node 对象的行为不像 yaml-cpp 中的类似值的对象?
- 从 const 对象访问非 const 方法
- 将非 const 对象用于 const 参数
- 如何键入用于const对象的自定义io操纵器
- 对临时对象的Const引用不会延长其生存期
- 正在通过const-ref未定义的行为捕获新构造的对象
- 具有成员变量的对象 Const 数组 = 先前索引成员变量的总和
- 为什么我构建的临时对象const不可变
- 强制用户声明对象const