Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/typo3/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 为什么在没有赋值运算符的情况下调用转换构造函数?_C++_Copy Constructor_Assignment Operator - Fatal编程技术网

C++ 为什么在没有赋值运算符的情况下调用转换构造函数?

C++ 为什么在没有赋值运算符的情况下调用转换构造函数?,c++,copy-constructor,assignment-operator,C++,Copy Constructor,Assignment Operator,今天我的问题是,为什么在没有用户提供的赋值运算符的情况下调用构造函数?我知道构造函数和赋值运算符在=符号方面的区别。如果在该行之前不存在对象,则隐式调用构造函数 std::string name=“Bjarne”//隐式构造函数 如果在该行之前已经存在对象,则调用赋值运算符 std::string name; name = "Bjarne"; // assignment operator 现在我这里有一个类编号,它是一个标记的并集。它只是一个数字,表示int或float。我定义了多个转换构

今天我的问题是,为什么在没有用户提供的赋值运算符的情况下调用构造函数?我知道构造函数和赋值运算符在
=
符号方面的区别。如果在该行之前不存在对象,则隐式调用构造函数

std::string name=“Bjarne”//隐式构造函数

如果在该行之前已经存在对象,则调用赋值运算符

std::string name;
name = "Bjarne";   // assignment operator
现在我这里有一个
类编号
,它是一个标记的并集。它只是一个数字,表示
int
float
。我定义了多个转换构造函数,使用户可以轻松地将值隐式地分配给
数字。我希望他们在这种情况下被呼叫:

编号num1=8

为了确定何时调用哪个构造函数,我将print语句放在构造函数的主体中

#include <cstdlib>
#include <iostream>

using std::cin;
using std::cout;
using std::cerr;
using std::endl;
using std::ostream;


/* Unions can be anonymous (unnamed).
 * This form is used when nesting a union inside a struct or class that contains an extra data member
 * to indicate what the union contains.
 * This arrangement is called a tagged union (or managed union).
 * It can be used as a "polymorphic" class which can be several things at once, for example to create an array
 * of different data types.
 */

class Number {
    friend ostream& operator<<(ostream& os, Number& num);
  public:
    Number(int i = 0) : DATA_TYPE(INTEGER), i(i) { cerr << "Number(" << i << ")\n"; }

    Number(unsigned int u) : DATA_TYPE(INTEGER), i(static_cast<int>(u)) { cerr << "Number((signed) " << i << ")\n"; }

    Number(float f) : DATA_TYPE(FLOAT), f(f) { cerr << "Number(" << f << ")\n"; }

    Number(double d) : DATA_TYPE(FLOAT), f(static_cast<float>(d)) { cerr << "Number((float) " << f << ")\n"; }    

    Number(const Number& rhs) : DATA_TYPE(rhs.DATA_TYPE), i(rhs.i) { cerr << "Number((Number) " << *this << ")\n"; }
  private:
        enum data_type { INTEGER, FLOAT } DATA_TYPE;

    union {
        int i;
        float f;
    };
};


ostream& operator<<(ostream& os, Number& num)
{
    switch (num.DATA_TYPE) {
        case Number::INTEGER:
      cout << num.i;
          break;
        case Number::FLOAT:
      cout << num.f;
          break;
    default:
      cout << 0;
      break;
    }

    return os;
}


int main()
{
    Number num1 = 5;  // conversion constructor
    cout << num1 << endl;
    num1 = 12.5;
    cout << num1 << endl;

    return EXIT_SUCCESS;
}
我看到当初始化
Number num1
时,调用以
int
为参数的构造函数。然后我打印
num1
的值。然后在下一行中,似乎调用了将
double
作为参数的构造函数。这很奇怪。在该行之前,
num1
已经作为一个对象存在。因此,它应该在逻辑上调用赋值运算符。我没有定义赋值运算符,因此我假设将调用编译器生成的赋值运算符

我想知道,在没有用户提供的赋值操作符的情况下,当我这样做时会发生什么<代码>num1=某物编译器提供的默认赋值运算符是否被调用,或者构造函数是否被调用?当对已经存在的对象调用构造函数时会发生什么?那个物体被“重建”了吗?那么在这种情况下会发生什么呢

我想知道,在没有用户提供的赋值操作符的情况下,当我这样做
num1=something时会发生什么

调用隐式
Number::operator=(常量Number&)

因此,从
double
构造一个临时数字

是调用编译器提供的默认赋值运算符还是调用构造函数

两者都有。构造函数是为临时对象而不是现有对象调用的

当对已经存在的对象调用构造函数时会发生什么? 那个物体被“重建”了吗?那么在这种情况下会发生什么呢

无法调用现有对象上的构造函数。你能做的最接近的事情就是

我想知道,在没有用户提供的赋值操作符的情况下,当我这样做
num1=something时会发生什么

调用隐式
Number::operator=(常量Number&)

因此,从
double
构造一个临时数字

是调用编译器提供的默认赋值运算符还是调用构造函数

两者都有。构造函数是为临时对象而不是现有对象调用的

当对已经存在的对象调用构造函数时会发生什么? 那个物体被“重建”了吗?那么在这种情况下会发生什么呢


无法调用现有对象上的构造函数。你能做的最接近的事情就是。

多亏了Jarod42,我才能够找到答案。因此,正如他所建议的,一个临时的
数字
对象被不可见地构造在
=
的右侧,然后调用赋值操作符,在该行的末尾,临时对象被销毁

我将以下代码添加到
Number
类中,以实际查看发生了什么

Number& operator=(const Number& rhs)
{
    cerr << "operator=(const Number&)" << endl;
return *this;
}

~Number() { cerr << "~Number()" << endl; }
产生以下输出:

Number(5)
Number((float) 12.5)
operator=(const Number&)
~Number()

Number(8)
operator=(const Number&)
~Number()
~Number()

多亏了Jarod42,我才明白这一点。因此,正如他所建议的,一个临时的
数字
对象被不可见地构造在
=
的右侧,然后调用赋值操作符,在该行的末尾,临时对象被销毁

我将以下代码添加到
Number
类中,以实际查看发生了什么

Number& operator=(const Number& rhs)
{
    cerr << "operator=(const Number&)" << endl;
return *this;
}

~Number() { cerr << "~Number()" << endl; }
产生以下输出:

Number(5)
Number((float) 12.5)
operator=(const Number&)
~Number()

Number(8)
operator=(const Number&)
~Number()
~Number()

这很奇怪,你以为会发生什么?代码编译时没有出错,所以会发生一些事情。最符合逻辑的是编译器看到了12.5,并使用
Number(double)
对其进行了转换。这很奇怪——您预期会发生什么?代码编译时没有出错,所以会发生一些事情。最符合逻辑的是编译器看到了12.5并使用
Number(double)
对其进行了转换。我以前不知道临时对象。这里也发生了同样的事情,
name=“Bjarne”
字符串文本
“Bjarne”
是否被转换为临时
std::string
对象,并且该对象是否随后被传递到
std::string::operator=(const string&)
重载赋值运算符?
std::string
在这种情况下提供了特殊功能(出于性能原因)为了避免构造临时对象,我还可以为我的类使用特殊的重载来接受
int
和其他数据类型,以避免构造临时对象。我认为,对于包含许多数据成员的大型类来说,这将是一个巨大的惩罚。我以前不知道临时对象。这里也发生了同样的事情吗,
name=“Bjarne”
字符串文本
“Bjarne”
是否被转换为临时
std::string
对象,并且该对象是否随后被传递到
std::string::operator=(const string&)
重载赋值运算符?
std::string
在这种情况下提供了特殊功能(出于性能原因)为了避免构造临时。因此,我还可以为我的类使用特殊重载来接受中的

Number(5)
Number((float) 12.5)
operator=(const Number&)
~Number()

Number(8)
operator=(const Number&)
~Number()
~Number()