- mongodb - 在 MongoDB mapreduce 中,如何展平值对象?
- javascript - 对象传播与 Object.assign
- html - 输入类型 ="submit"Vs 按钮标签它们可以互换吗?
- sql - 使用 MongoDB 而不是 MS SQL Server 的优缺点
我认为既然 C++11 用户定义类型对象应该使用新的 {...}
语法而不是旧的 (...)
语法(除了为 std::initializer_list
和类似参数重载的构造函数(例如 std::vector
: size ctor vs 1 elem init_list ctor))。
好处是:没有狭窄的隐式转换,最麻烦的解析没有问题,一致性(?)。我认为没有问题,因为我认为它们是相同的(除了给出的示例)。
但他们不是。
{}
调用默认构造函数。
... 除非:
那么看起来是不是用value来初始化对象?...即使对象已经删除了默认构造函数,{}
也可以创建对象。这难道不是违背了已删除构造函数的全部目的吗?
...除非:
然后 调用已删除的构造函数
失败。
...除非:
然后它会因缺少字段初始值设定项而失败。
但是你可以使用 {value}
来构造对象。
好吧,也许这和第一个异常一样(值初始化对象)
...除非:
那么 {}
和 {value}
都不能创建对象。
我确定我错过了一些。具有讽刺意味的是,它被称为uniform 初始化语法。我再说一遍:UNIFORM初始化语法。
这是什么疯子?
struct foo {
foo() = delete;
};
// All bellow OK (no errors, no warnings)
foo f = foo{};
foo f = {};
foo f{}; // will use only this from now on.
struct foo {
foo() = delete;
foo(int) = delete;
};
foo f{}; // OK
struct foo {
foo() = delete;
foo(int) {};
};
foo f{}; // error call to deleted constructor
struct foo {
int a;
foo() = delete;
};
foo f{}; // error use of deleted function foo::foo()
foo f{3}; // OK
struct foo {
int a;
foo() = delete;
foo(int) = delete;
};
foo f{}; // ERROR: missing initializer
foo f{3}; // OK
struct foo {
int a = 3;
foo() = delete;
};
/* Fa */ foo f{}; // ERROR: use of deleted function `foo::foo()`
/* Fb */ foo f{3}; // ERROR: no matching function to call `foo::foo(init list)`
最佳答案
当以这种方式看待事物时,很容易说对象的初始化方式完全困惑。
最大的区别在于 foo
的类型:是否是聚合类型。
It is an aggregate if it has:
- no user-provided constructors (a deleted or defaulted function does not count as user-provided),
- no private or protected non-static data members,
- no brace-or-equal-initializers for non-static data members (since c++11 until (reverted in) c++14)
- no base classes,
- no virtual member functions.
所以:
foo
是一个聚合foo
不是聚合4.9
没有实现这个。5.2.0
可以5.2.1 ubuntu
没有(可能是回归)The effects of list initialization of an object of type T are:
- ...
- If T is an aggregate type, aggregate initialization is performed. This takes care of scenarios A B D E (and F in C++14)
- Otherwise the constructors of T are considered in two phases:
- All constructors that take std::initializer_list ...
- otherwise [...] all constructors of T participate in overload resolution [...] This takes care of C (and F in C++11)
- ...
:
Aggregate initialization of an object of type T (scenarios A B D E (F c++14)):
- Each non-static class member, in order appearance in the class definition, is copy-initialized from the corresponding clause of the initializer list. (array reference omitted)
TL;DR
所有这些规则看起来仍然非常复杂且令人头疼。我个人为自己过度简化了这一点(如果我因此在脚上开枪,那就这样吧:我想我会在医院呆两天而不是头痛十几天):
Doesn't this beat the whole purpose of a deleted constructor?
嗯,我不知道,但解决方案是使 foo
不是聚合。不增加开销并且不改变对象使用的语法的最通用形式是使其继承自空结构:
struct dummy_t {};
struct foo : dummy_t {
foo() = delete;
};
foo f{}; // ERROR call to deleted constructor
在某些情况下(我猜根本没有非静态成员),另一种方法是删除析构函数(这将使对象在任何上下文中都不可实例化):
struct foo {
~foo() = delete;
};
foo f{}; // ERROR use of deleted function `foo::~foo()`
此答案使用从以下网站收集的信息:
非常感谢 @M.M谁帮助纠正和改进了这篇文章。
关于c++ - 删除了默认构造函数。仍然可以创建对象...有时,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33988297/
C语言sscanf()函数:从字符串中读取指定格式的数据 头文件: ?
最近,我有一个关于工作预评估的问题,即使查询了每个功能的工作原理,我也不知道如何解决。这是一个伪代码。 下面是一个名为foo()的函数,该函数将被传递一个值并返回一个值。如果将以下值传递给foo函数,
CStr 函数 返回表达式,该表达式已被转换为 String 子类型的 Variant。 CStr(expression) expression 参数是任意有效的表达式。 说明 通常,可以
CSng 函数 返回表达式,该表达式已被转换为 Single 子类型的 Variant。 CSng(expression) expression 参数是任意有效的表达式。 说明 通常,可
CreateObject 函数 创建并返回对 Automation 对象的引用。 CreateObject(servername.typename [, location]) 参数 serv
Cos 函数 返回某个角的余弦值。 Cos(number) number 参数可以是任何将某个角表示为弧度的有效数值表达式。 说明 Cos 函数取某个角并返回直角三角形两边的比值。此比值是
CLng 函数 返回表达式,此表达式已被转换为 Long 子类型的 Variant。 CLng(expression) expression 参数是任意有效的表达式。 说明 通常,您可以使
CInt 函数 返回表达式,此表达式已被转换为 Integer 子类型的 Variant。 CInt(expression) expression 参数是任意有效的表达式。 说明 通常,可
Chr 函数 返回与指定的 ANSI 字符代码相对应的字符。 Chr(charcode) charcode 参数是可以标识字符的数字。 说明 从 0 到 31 的数字表示标准的不可打印的
CDbl 函数 返回表达式,此表达式已被转换为 Double 子类型的 Variant。 CDbl(expression) expression 参数是任意有效的表达式。 说明 通常,您可
CDate 函数 返回表达式,此表达式已被转换为 Date 子类型的 Variant。 CDate(date) date 参数是任意有效的日期表达式。 说明 IsDate 函数用于判断 d
CCur 函数 返回表达式,此表达式已被转换为 Currency 子类型的 Variant。 CCur(expression) expression 参数是任意有效的表达式。 说明 通常,
CByte 函数 返回表达式,此表达式已被转换为 Byte 子类型的 Variant。 CByte(expression) expression 参数是任意有效的表达式。 说明 通常,可以
CBool 函数 返回表达式,此表达式已转换为 Boolean 子类型的 Variant。 CBool(expression) expression 是任意有效的表达式。 说明 如果 ex
Atn 函数 返回数值的反正切值。 Atn(number) number 参数可以是任意有效的数值表达式。 说明 Atn 函数计算直角三角形两个边的比值 (number) 并返回对应角的弧
Asc 函数 返回与字符串的第一个字母对应的 ANSI 字符代码。 Asc(string) string 参数是任意有效的字符串表达式。如果 string 参数未包含字符,则将发生运行时错误。
Array 函数 返回包含数组的 Variant。 Array(arglist) arglist 参数是赋给包含在 Variant 中的数组元素的值的列表(用逗号分隔)。如果没有指定此参数,则
Abs 函数 返回数字的绝对值。 Abs(number) number 参数可以是任意有效的数值表达式。如果 number 包含 Null,则返回 Null;如果是未初始化变量,则返回 0。
FormatPercent 函数 返回表达式,此表达式已被格式化为尾随有 % 符号的百分比(乘以 100 )。 FormatPercent(expression[,NumDigitsAfterD
FormatNumber 函数 返回表达式,此表达式已被格式化为数值。 FormatNumber( expression [,NumDigitsAfterDecimal [,Inc
我是一名优秀的程序员,十分优秀!