C++ 复制初始化和直接初始化之间有区别吗?

C++ 复制初始化和直接初始化之间有区别吗?,c++,initialization,C++,Initialization,假设我有这个函数: void my_test() { A a1 = A_factory_func(); A a2(A_factory_func()); double b1 = 0.5; double b2(0.5); A c1; A c2 = A(); A c3(A()); } 在每个分组中,这些语句是否相同?或者在某些初始化中是否有额外的(可能是可优化的)副本 我见过有人说这两件事。请引用文本作为证据。也请添加其他案例。作业不同于初

假设我有这个函数:

void my_test()
{
    A a1 = A_factory_func();
    A a2(A_factory_func());

    double b1 = 0.5;
    double b2(0.5);

    A c1;
    A c2 = A();
    A c3(A());
}
在每个分组中,这些语句是否相同?或者在某些初始化中是否有额外的(可能是可优化的)副本


我见过有人说这两件事。请引用文本作为证据。也请添加其他案例。

作业不同于初始化

以下两行都进行初始化。完成单个构造函数调用:

A a1 = A_factory_func();  // calls copy constructor
A a1(A_factory_func());   // calls copy constructor
但这并不等于:

A a1;                     // calls default constructor
a1 = A_factory_func();    // (assignment) calls operator =
我目前没有文本来证明这一点,但很容易进行实验:

#include <iostream>
using namespace std;

class A {
public:
    A() { 
        cout << "default constructor" << endl;
    }

    A(const A& x) { 
        cout << "copy constructor" << endl;
    }

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

int main() {
    A a;       // default constructor
    A b(a);    // copy constructor
    A c = a;   // copy constructor
    c = b;     // operator =
    return 0;
}
#包括
使用名称空间std;
甲级{
公众:
A(){

cout赋值不同于初始化

以下两行都进行初始化。完成单个构造函数调用:

A a1 = A_factory_func();  // calls copy constructor
A a1(A_factory_func());   // calls copy constructor
但这并不等于:

A a1;                     // calls default constructor
a1 = A_factory_func();    // (assignment) calls operator =
我目前没有文本来证明这一点,但很容易进行实验:

#include <iostream>
using namespace std;

class A {
public:
    A() { 
        cout << "default constructor" << endl;
    }

    A(const A& x) { 
        cout << "copy constructor" << endl;
    }

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

int main() {
    A a;       // default constructor
    A b(a);    // copy constructor
    A c = a;   // copy constructor
    c = b;     // operator =
    return 0;
}
#包括
使用名称空间std;
甲级{
公众:
A(){

cout这些情况中有很多都取决于对象的实现,因此很难给出具体的答案

考虑一下这个案例

A a = 5;
A a(5);
在这种情况下,假设一个合适的赋值运算符&初始化接受单个整数参数的构造函数,我如何实现所述方法会影响每一行的行为。然而,通常的做法是,其中一个在实现中调用另一个,以消除重复的代码(尽管在如此简单的情况下,没有真正的目的。)

<>编辑:如其他响应中提到的,第一行实际上将调用复制构造函数。将与赋值运算符相关的注释视为与单独赋值有关的行为。

也就是说,编译器如何优化代码将有它自己的影响。如果我让初始化构造函数调用“=”运算符,如果编译器没有进行优化,那么顶行将执行2次跳转,而不是底行中的一次跳转


现在,对于最常见的情况,您的编译器将在这些情况下进行优化,并消除此类低效。因此,您所描述的所有不同情况实际上都是相同的。如果您想确切了解正在执行的操作,可以查看编译器的目标代码或程序集输出。

许多se案例取决于对象的实现,因此很难给出具体的答案

考虑一下这个案例

A a = 5;
A a(5);
在这种情况下,假设一个合适的赋值运算符&初始化接受单个整数参数的构造函数,我如何实现所述方法会影响每一行的行为。然而,通常的做法是,其中一个在实现中调用另一个,以消除重复的代码(尽管在如此简单的情况下,没有真正的目的。)

<>编辑:如其他响应中提到的,第一行实际上将调用复制构造函数。将与赋值运算符相关的注释视为与单独赋值有关的行为。

也就是说,编译器如何优化代码将有它自己的影响。如果我让初始化构造函数调用“=”运算符,如果编译器没有进行优化,那么顶行将执行2次跳转,而不是底行中的一次跳转


现在,对于最常见的情况,您的编译器将在这些情况下进行优化,并消除此类低效。因此,您所描述的所有不同情况实际上都是相同的。如果您想确切了解正在执行的操作,可以查看编译器的目标代码或程序集输出。

doubleb1=0.5;
是构造函数的隐式调用

双b2(0.5);
是显式调用

查看以下代码以查看差异:

#include <iostream>
class sss { 
public: 
  explicit sss( int ) 
  { 
    std::cout << "int" << std::endl;
  };
  sss( double ) 
  {
    std::cout << "double" << std::endl;
  };
};

int main() 
{ 
  sss ddd( 7 ); // calls int constructor 
  sss xxx = 7;  // calls double constructor 
  return 0;
}
#包括
类sss{
公众:
显式sss(int)
{ 

std::cout
双b1=0.5;
是构造函数的隐式调用

双b2(0.5);
是显式调用

查看以下代码以查看差异:

#include <iostream>
class sss { 
public: 
  explicit sss( int ) 
  { 
    std::cout << "int" << std::endl;
  };
  sss( double ) 
  {
    std::cout << "double" << std::endl;
  };
};

int main() 
{ 
  sss ddd( 7 ); // calls int constructor 
  sss xxx = 7;  // calls double constructor 
  return 0;
}
#包括
类sss{
公众:
显式sss(int)
{ 

std::cout第一个分组:它取决于
A_factory_func
返回的内容。第一行是复制初始化的示例,第二行是直接初始化。如果
A_factory_func
返回一个
A
对象,那么它们是等价的,它们都调用
A
的复制构造函数,否则第一个版本对于返回类型为
A\u factory\u func
或相应的
A
构造函数,sion从可用的转换运算符创建类型为
A
的右值,然后调用复制构造函数从该临时构造函数构造
a1
。第二个版本尝试找到一个合适的构造函数,该构造函数接受的任何内容e> _factory_func
返回,或获取返回值可以隐式转换为的内容

第二个分组:逻辑完全相同,只是内置类型没有任何外来构造函数,所以实际上它们是相同的


第三组:
c1
默认初始化,
c2
从临时初始化的值复制初始化。如果用户提供了默认构造函数(如果有的话),则具有pod类型的
c1
的任何成员(或成员的成员等)都可能不会初始化不要显式初始化它们。对于
c2
,这取决于是否有用户提供的复制构造函数,以及该构造函数是否适当地初始化了这些成员,但是临时的成员都将被初始化(如果没有显式初始化,则初始化为零).正如litb所指出的,
c3
是一个陷阱。它实际上是一个函数声明。

第一组:它取决于什么是工厂函数B(A const&)
B(A const&)
operator B(A&);
class A
{
    A(int) { }      // converting constructor
    A(int, int) { } // converting constructor (C++11)
};

class B
{
    explicit B(int) { }
    explicit B(int, int) { }
};
int main()
{
    A a1 = 1;      // OK: copy-initialization selects A::A(int)
    A a2(2);       // OK: direct-initialization selects A::A(int)
    A a3 {4, 5};   // OK: direct-list-initialization selects A::A(int, int)
    A a4 = {4, 5}; // OK: copy-list-initialization selects A::A(int, int)
    A a5 = (A)1;   // OK: explicit cast performs static_cast

//  B b1 = 1;      // error: copy-initialization does not consider B::B(int)
    B b2(2);       // OK: direct-initialization selects B::B(int)
    B b3 {4, 5};   // OK: direct-list-initialization selects B::B(int, int)
//  B b4 = {4, 5}; // error: copy-list-initialization does not consider B::B(int,int)
    B b5 = (B)1;   // OK: explicit cast performs static_cast
}
A a1 = 1;        // this is copy initialization
A a2(2);         // this is direct initialization
B b2(2);        // this is direct initialization
B b5 = (B)1;    // not problem if you either use of assign to initialize and cast it as static_cast