17

它是简单的偏好还是有特定的情况需要一个而不是另一个?我指的是以下变体进行初始化

T t(e); // direct initialization
T t = e; // copy initialization
4

2 回答 2

20

您描述的事物的实际名称不是隐式和显式分配,而是:

  • 复制初始化:T x = a;
  • 直接初始化:T x(a);

它们是等价的,尤其是在需要转换的上下文中,例如当T是类类型并且a是不同类型时(有关甚至不涉及转换的上下文示例,请参见 Alf 注释)。考虑以下代码:

class Test
{
public:
    explicit Test(int i) { /* ... */ }
};

int main()
{
    Test t(0);  // OK : calls Test::Test(int)
    Test u = 0; // KO : constructor is marked explicit
}

解释标准(8.5/14):

  • 对于源类型与目标类相同或其派生类的直接初始化和复制初始化,考虑构造函数
  • main对于其他复制初始化情况,例如我的示例中的第二行,考虑了用户定义的转换顺序。由于关键字Test不允许使用构造函数进行隐式转换explicit,因此第二行无法编译。
于 2010-11-27T20:42:08.977 回答
11

直接初始化

std::istringstream  stream( "blah blah" );

当有问题的类型(此处std::istringstream来自 C++ 标准库)没有可访问的复制构造函数时,这是必需的。

复制初始化,例如

std::istringstream  stream = "blah blah";   //! NOT VALID

需要一个可访问的复制构造函数,因为它的执行就像在 的右侧创建了一个临时对象=,并且好像该临时对象随后用于初始化正在声明的变量。

另一方面,在 C++98 中,需要复制初始化语法才能使用花括号初始化器。例如,直接初始化不能用于初始化聚合。但是您可以使用带有花括号初始化程序的复制初始化:

#include <string>
using namespace std;

struct Answer
{
    int     nVotes;
    string  description;
};    

int main()
{
    Answer const  incorrect   = { 26, "they're the same!" };
    Answer const  correct     = { -1, "nah, they're different, actually" };
}

因此,存在显着差异。

由于清晰,我通常更喜欢复制初始化语法。但有时,如上所示,不幸的是,直接初始化是必要的。有些人,例如 C++ 教科书作者 Francis Glassborow,转而将直接初始化作为他们首选的初始化语法(我不知道为什么,我的眼睛不太清楚,并引入了“最令人头疼的解析”问题),并且对他们来说不幸的是,在某些情况下需要进行复制初始化。

干杯&hth.,

于 2010-11-28T04:43:40.613 回答