为什么会调用复制操作员?

Why did the copy operator get called?

在最后一行myA = foo(myOtherB);,函数将return键入一个类型A的对象,因此;这就像说 `myA = input,但为什么是复制构造函数?

输出:

B foo()
 A copy ctor //what calls this?
 A op=

要调用复制构造函数,我们必须在初始化期间使用赋值运算符,例如:B newB = myOtherB;

#include <iostream>
using namespace std;

class A {
public:
 A() { cout << "A ctor" << endl; }
 A(const A& a) { cout << "A copy ctor" << endl; }
 virtual ~A() { cout << "A dtor" << endl; }
 virtual void foo() { cout << "A foo()" << endl; }
 virtual A& operator=(const A& rhs) { cout << "A op=" << endl; }
};

class B : public A {
public:
 B() { cout << "B ctor" << endl; }
 virtual ~B() { cout << "B dtor" << endl; }
 virtual void foo() { cout << "B foo()" << endl; }
 protected:
 A mInstanceOfA; // don't forget about me!
};

A foo(A& input) {
 input.foo();
 return input;
}
int main() {
 B myB;
 B myOtherB;
 A myA;
 myOtherB = myB;
 myA = foo(myOtherB);
}

At the last line myA = foo(myOtherB);, the function will return type an object of type B

不正确。您的函数 returns 类型为 A 的对象(按值)。这意味着,您为要构造的对象提供的任何值都将用于构造该确切类型的新对象。所以换句话说:

int foo(float a) {
    return a + 0.5;
}

int u;

u = foo(9.3);

// u has a value of 10

不要指望 u 可以保存 int 不能保存的值。

如果您使用用户定义的类型,同样的事情:

A foo(A& input) {
 input.foo();
 return input; // this expression returns a new A
               // using the value of `input`
}

A myA;

myA = foo(myOtherB);

// why would `myA` be anything else than the value of an A?

那么,这里发生了什么?

B foo()
 A copy ctor //what calls this?
 A op=
A foo(A& input) {
 input.foo(); // prints B foo, virtual call. a reference to A that
              // points to an object of subclass type B

 return input; // copy `input` into the return value object
}

然后,operator= 被调用。

cppreference

具体来说:

The copy constructor is called whenever an object is initialized (by direct-initialization or copy-initialization) from another object of the same type (unless overload resolution selects a better match or the call is elided), which includes

  • initialization: T a = b; or T a(b);, where b is of type T;
  • function argument passing: f(a);, where a is of type T and f is void f(T t);
  • function return: return a; inside a function such as T f(), where a is of type T, which has no move constructor.