15

原始类型没有构造函数已经被一遍又一遍地重新散列。例如_bar,当我调用时,它没有初始化为 0 Foo()

class Foo{
    int _bar;
};

所以显然int()不是构造函数。但它什么名字?

在这个例子中,我想说i的是:(构造?初始化?吃错了?)

for(int i{}; i < 13; ++i)

Loki Astari在这里提到该技术有某种名称。

编辑回应迈克西摩

#include <iostream>

using namespace std;

class Foo{
    int _bar;
public:
    void printBar(){ cout << _bar << endl; }
};

int main()
{
    Foo foo;

    foo.printBar();

    Foo().printBar();

    return 0;
}

在 Visual Studio 2013 上运行此代码会产生:

3382592
3382592

有趣的是 gcc 4.8.1 的产量:

134514651
0

4

3 回答 3

9

原始类型没有构造函数已经被一遍又一遍地重新散列。

这是正确的。

例如,当我调用时,此栏未初始化为 0Foo()

是的。Foo()指定值初始化,对于像这样没有用户提供构造函数的类,这意味着它在初始化其成员之前是零初始化的。所以_bar以零值结束。(尽管如评论中所述,一种流行的编译器没有正确地对此类类进行值初始化。)

如果您要使用默认初始化,它将不会被初始化。你不能用临时的来做到这一点;但是声明的变量Foo f;或对象new F将被默认初始化。原始类型的默认初始化什么都不做,给它们留下一个不确定的值。

如果该类具有用户提供的默认构造函数,并且该构造函数没有专门初始化,它也不会被初始化_bar。同样,它将被默认初始化,没有任何效果。

所以显然 int() 不是构造函数。但它叫什么名字?

作为一个表达式,它是一个值初始化的临时类型int

从语法上讲,它是“显式类型转换(功能符号)”的特例;但是将该术语用于除类型转换之外的任何内容都会令人困惑。

在这个例子中,我想说i的是:(构造?初始化?吃错了?)

初始化。如果您想更具体,列表初始化(带有空列表)、值初始化或零初始化。

于 2014-12-12T12:29:16.313 回答
6

这是什么int()(请记住,从语法上讲,int它是一个简单类型说明符):

[C++11: 5.2.3/1]:一个简单类型说明符(7.1.6.2) 或类型名称说明(14.6) 后跟一个带括号的表达式列表,构造一个给定表达式列表的指定类型的值。如果表达式列表是单个表达式,则类型转换表达式等效于(在定义上,并且如果在含义上定义)对应的强制转换表达式(5.4)。如果指定的类型是类类型,则类类型应是完整的。如果表达式列表指定了多个值,则类型应为具有适当声明的构造函数(8.5、12.1)的类,并且表达式T(x1, x2, ...)在效果上等同于声明T t(x1, x2, ...);对于一些发明的临时变量t,结果是t作为纯右值的值。

通俗地说,它代表了一个int带有空初始化器的临时结构。不过,我认为您很难为整个构造找到正式名称。

这与 不同,后者是具有初始化程序的命名对象int i{}的完整声明i:您已被声明、构造和初始化。

(我认为这与 Loki 在对该链接答案的评论中所说的话无关。)

于 2014-12-12T12:23:25.587 回答
-1

如果需要,可以将其称为伪构造函数,镜像析构函数的术语(伪析构函数调用在 C++11 §5.2.4 中讨论)。无论如何,int()是 type 的默认值int,即 0。

关于“原始类型没有构造函数”的断言,这是一个相当愚蠢和不切实际的观点。从形式的角度来看,原始类型没有构造函数,但是那些坚持该断言的人根本就没有那么喜欢形式。此外,从机器代码的角度来看,它们不是,但是对于那些认为断言很重要的人来说,机器代码就像魔术一样。但是,有一个区别,即从机器代码的角度来看,常见的非原始 POD 类型也可能缺少构造函数(它们确实有正式的构造函数),我再次怀疑那些提出该断言的人是否意识到问题,即我认为他们没有资格发表意见。任何绝对的术语声明都需要同样的考虑:你几乎可以肯定,

相反,当您在原始类型的上下文中听到例如“构造”或“构造函数调用”时,请考虑它的含义。形式只是定义问题。重要的是,除了语言律师讨论,无论如何它是给定的,是有一个有效的概念模型。


综上所述,表达式T()不是形式上的“构造函数”,它不是机器代码级别的构造函数,在任何有意义的概念模型中,它在概念上也不是构造函数。

可以构造函数调用(实际上,默认构造函数的定义是它可以在源代码级别调用,不带参数),但请注意构造函数调用没有语法类别。

考虑到以上所有内容,我将其称为构造函数调用,当需要更精确时,对于原始类型,T我将其称为伪构造函数调用


如果有人因此批评我,我会挑战他们决斗。


请注意,关于您的陈述

它被反复强调原始类型没有构造函数。例如,当我调用时,此栏未初始化为 0Foo()

表达式Foo()执行值初始化,以便实例(在这种情况下)归零。

关于没有初始化器的基本类型的局部自动变量的初始化通常缺乏初始化,对于没有用户定义构造函数的任何类型,您都会遇到相同的情况,即使有一个使用定义的构造函数,如果该构造函数没有初始化事物。

这有时会让 C++ 初学者感到震惊。

于 2014-12-12T12:48:40.133 回答