什么时候应该使用直接初始化和复制初始化?

时间:2010-11-27 19:59:53

标签: c++ implicit-conversion explicit-constructor copy-initialization

是仅仅是偏好还是有特定的情况需要一个人而不是另一个人?我引用了以下变体进行初始化

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

2 个答案:

答案 0 :(得分:19)

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

  • 复制初始化: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构造函数进行隐式转换,因此第二行无法编译。

答案 1 :(得分:10)

直接初始化,如

std::istringstream  stream( "blah blah" );
当有问题的类型(此处为C ++标准库中的std::istringstream)没有可访问的复制构造函数时,

是必需的。

复制初始化,如

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反而将直接初始化作为他们首选的初始化语法(我不知道为什么,我的眼睛不太清楚,并引入了“最令人烦恼的解析”问题),对于他们来说,这是必要的在某些情况下复制初始化,这是不幸的。

干杯&amp;第h。,