构造函数是否与“=”运算符执行相同的操作?

Do constructors do the same thing as the '=' operator?

提问人:Jibel 提问时间:5/27/2023 最后编辑:Jibel 更新时间:5/29/2023 访问量:166

问:

  1. 当我们没有定义任何运算符时,编译器如何知道 使用构造函数?=
  2. 构造函数不是只在定义变量时才调用的吗?
#include <string>

class Person
{
    public:
    std::string name;
    Person(const char* full_name) : name(full_name) {}
};

int main()
{
    Person p1("Jibel Sadeghi"); // This is ok because we declared the constructor with a const char*, but...
    /* When we didn't overload the '=' operator for 'const char*',
       how the next lines don't have any errors? */
    p1 = "Ben Sadeghi";
}
C++ OOP 构造函数 operator-重载 赋值运算符

评论

2赞 Ted Lyngmo 5/27/2023
诀窍是实现所有 5 个并记录发生的情况。
3赞 BoP 5/27/2023
您刚刚告诉编译器两种从其他类型创建的方法,因此它会在需要时这样做。如果要限制构造函数的使用,可以创建构造函数。Personexplicit
1赞 Pepijn Kramer 5/27/2023
如果您不创建自己的任何构造函数,则某些构造函数将隐式可用,这包括隐式复制/赋值构造函数
1赞 Ted Lyngmo 5/27/2023
下一个技巧:做一个最小的可重现的例子
1赞 heap underrun 5/27/2023
因为您没有将构造函数定义为 ,所以它被称为转换构造函数explicit

答:

7赞 Ben Voigt 5/27/2023 #1

构造函数不是只在定义变量时才调用的吗?

不。在创建对象(类的实例)时使用构造函数。

该对象可以保存在变量中,也可以保存在数组的元素中,也可以动态分配,或者(在这种情况下)是一个临时对象。

当我们没有定义任何 = 运算符时,编译器如何知道使用构造函数?

您的类具有默认的复制赋值运算符,带有签名

Person& Person::operator=(const Person& assign_from);

和默认的移动赋值运算符,带签名

Person& Person::operator=(Person&& move_assign_from);

当编译器尝试编译时

p1 = "Ben Sadeghi";

它看到它需要 ,查看所有候选参数(默认有两个,因为您没有提供任何候选参数),并且对于每个候选参数,它尝试将实际参数转换为形式参数的类型。Person::operator=()

对于复制赋值,形式参数具有 type,实际参数具有 type ,并且有一个隐式构造函数能够执行转换。所以可以调用,后跟 .const Person&const char[12]Person::Person(const char*)Person& Person::operator=(const Person&)

对于移动赋值,形式参数具有 type,实际参数具有 type ,并且有一个能够执行转换的隐式构造函数。所以可以调用,后跟 .Person&&const char[12]Person::Person(const char*)Person& Person::operator=(Person&&)

这个参数比 更适合临时人,所以最后选择了后面的序列。Person&&const Person&Person::Person(const char*)Person& Person::operator=(Person&&)

评论

1赞 Ben Voigt 5/27/2023
@fabian:啊,是的,如果任何 operator= 是用户声明的,或者如果复制构造函数是用户声明的,那么默认的移动就会被击败,但这里它们不是,所以默认的移动分配不会被删除。
0赞 Peter 5/27/2023
还有一个从 到 的隐式转换,以便调用const char[12]const char *Person::Person(const char *)
0赞 Ben Voigt 5/29/2023
@Peter:是的,这是一个“免费”的转换。