什么是"事情之间的区别;"和"事情=事情();",什么时候应该使用一个而不是另一个?

时间:2014-10-04 10:19:34

标签: c++ variables object

我不明白以下两个陈述之间的区别:

Thing thing;

Thing thing = Thing();

两者都创建一个Thing对象并将其放在变量thing中,对吗?如果是这样,有两个问题:

1-两者之间有哪些技术差异?

2-我应该何时使用另一个?

请注意:

A-我没有使用C ++ 11。

B- C ++新手,请使用新手友好的词语。

4 个答案:

答案 0 :(得分:4)

Thing thing;

是默认初始化。如果Thing是类类型,它会调用Thing的默认构造函数,就是这样。

Thing thing = Thing();

value-initializes临时Thing,然后将该临时副本复制/移动到thing。在实践中,编译器将忽略复制/移动,使其有效地进行值初始化,但这仍然需要复制/移动构造函数可用。获取值初始化语义需要= Thing();语法,因为Thing thing();是一个令人烦恼的解析。 *

值初始化和默认初始化之间的区别在于,在某些情况下(确切的情况depend on the version of the standard,但是没有用户提供的构造函数的非联合类类型,以及非类非数组类型,以及这些类型的数组在所有版本中都有资格),值初始化将在调用默认构造函数之前首先进行零初始化。

如果Thing可以是非类(例如,在模板中)或者是将获得零初始化处理的类类型(例如,POD类)并且您是使用第二个版本是有帮助的希望它有明确的价值观。

* Thing thing{};在初始化语义上与C ++ 14中的普通值初始化略有不同。

答案 1 :(得分:3)

符号

Thing thing = Thing();
执行复制初始化的

可以在C ++ 03模板代码中用于有效地默认构造Thing。问题是,这也适用于内置类型Thing,例如int。这种扭曲的表示法因为写Thing thing();只是声明一个函数(一个特别的“最令人烦恼的解析”)。

在C ++ 11中,可以改为编写

Thing thing{};

C ++ 03中的另一种技术是将Thing包裹在struct中,如下所示:

struct Initialized_thing
{
    Thing thing;
    Initialized_thing(): thing() {}
};

答案 2 :(得分:0)

不同之处在于,如果无法访问复制或移动构造函数,编译器可能会为第二个定义发出错误。例如,它们可能被定义为私有或已删除。

Thing thing;

Thing thing = Thing(); // there may be a compiler error

例如,考虑以下程序

int main() 
{
    class A
    {
    private:
        A( const A & );
    public:
        A() {}  
    };

    A a;

    return 0;
}

上面的程序将成功编译,而下面的程序将不会被编译(如果只有编译器不是例如MS VC ++ 2010)

int main() 
{
    class A
    {
    private:
        A( const A & );
    public:
        A() {}  
    };

    A a = A();

    return 0;
}

本声明中的另一个区别

A a;

a是默认初始化

在本声明中

A a = A();

a初始化值。

来自C ++标准

  

2表达式T(),其中T是简单类型说明符或   非数组完整对象类型的typename-specifier或   (可能是cv-qualified)void类型,创建指定的prvalue   type,其值是由value-initializing(8.5)生成的   T型物体;没有为void()情况进行初始化。

考虑另一个例子

int main() 
{
    class A
    {
        int x;
    };

    A a1;
    A a2 = A();     

    return 0;
}

对于x的a1值将是未指定的,而对于s2的x值将等于0.

答案 3 :(得分:0)

正如其他人编写的语法

Thing obj;

default-initialize您的对象,而语法

Thing obj = Thing();

value-initialize您的对象。

第二种语法会导致涉及更多内容:

  • 应该可以访问移动/复制构造函数
  • 临时值已初始化
  • 复制省略发生

它们通常用于不同的目的,虽然第一个是最常用于初始化对象的,但后者在值初始化含义上是不同的。

我建议阅读文档以了解值和默认初始化之间的差异,无论如何,显示差异的简单示例如下:

class Thing {
  public:

  int data;

  Thing() {
      cout << "default ctor" << endl;
  }

  Thing(const Thing&) {
      cout << "copy ctor" << endl;
  }

  const Thing& operator=(const Thing&) {
      cout << "operator=" << endl;
      return *this;
  }
};

struct Thingy {
    int data;  
};

int main() {
  cout << is_pod<Thing>::value << endl; // Thing is NOT pod

  Thing thing; // Calls default constructor
  cout << thing.data << endl; // Garbage

  Thing thing2 = Thing(); // Copy elision is able to optimize this (standard-defined 12.8/31). Anyway a copy/move constructor must be accessible
  cout << thing2.data << endl; // Garbage

  // -----------------------------------------------------

  cout << is_pod<Thingy>::value << endl; // Thingy IS pod

  Thingy thingy1;
  cout << thingy1.data << endl; // garbage

  Thingy thingy2 = Thingy();
  cout << thingy2.data << endl; // zero-initialized!
}

上面的代码将打印

0 // Not a POD
default ctor
-1326900592 // garbage
default ctor
-1326900592 // garbage
// ---------------------------
1 // POD
-1326900592 // garbage
0           // zero-initialized