一个参数构造函数和赋值运算符

时间:2014-08-18 10:10:37

标签: c++

请考虑以下代码:

#include <iostream>
using namespace std;

class A{

private:
    int a;
public:
    A(int);
    void print();
    void operator =(int);
};

// One argument constructor
A::A(int b){
    cout<<"Inside one argument constructor"<<endl;
    this->a=b;
}

void A:: operator =(int b){
    cout<<"Inside operator function"<<endl;
    this->a = b;
}

void A::print(){
    cout<<"Value of a ="<<a<<endl;
}

int main() {

    /* INITIALIZATION */
    A obj1=2;
    obj1.print();

    /* ASSIGNMENT */
    obj1=3;
    obj1.print();

    return 0;
}

上面代码的输出可以在这里看到:http://ideone.com/0hnZUb。它是:

Inside one argument constructor
Value of a =2
Inside operator function
Value of a =3

所以我观察到的是,在初始化期间,会调用单参数构造函数,但在赋值期间,会调用重载的赋值运算符函数。此行为是由C ++标准强制执行还是特定于编译器?有人能引用定义此行为的标准部分吗?

2 个答案:

答案 0 :(得分:2)

它是标准的,我想构造函数用于初始化并且赋值运算符用于赋值也就不足为奇了。在C ++标准中,第12.8节 - 复制和移动类对象 - 以

开头
  

可以通过两种方式复制或移动类对象:初始化(12.1,8.5),包括函数参数传递(5.2.2)和函数值返回(6.6.3);并通过转让(5.17)。从概念上讲,这两个操作是由复制/移动构造函数(12.1)和复制/移动赋值运算符(13.5.3)实现的。

答案 1 :(得分:1)

这是标准行为。

我搜索了最新的C ++标准,ISO / IEC 14882:2011(E),编程语言C ++。

以下代码

A obj1 = 2;

是初始化。第8.5节初始化者,第16节对此进行了描述。

  

16初始值设定项的语义如下。目标类型是要初始化的对象或引用的类型,源类型是初始化表达式的类型。如果初始化程序不是单个(可能带括号的)表达式,则不定义源类型。

以下部分内容很长。我只引用与您的示例代码相关的内容。

  

- 如果目标类型是(可能是cv限定的)类类型:

     

- 如果初始化是直接初始化,或者它是复制初始化,其中源类型的cv-nonqualified版本与目标类的类相同,或者是派生类,则构造函数被视为。列举了适用的构造函数(13.3.1.3),并通过重载解析(13.3)选择最佳构造函数。调用所选的构造函数来初始化对象,初始化表达式或表达式列表作为其参数。如果没有构造函数适用,或者过载解析是不明确的,则初始化是不正确的。

第13.3.1.3节是构造函数的初始化。

编译为8.5和13.3.1.3,构造函数

A(int);
选择

来初始化obj1。


至于第二个

obj1 = 3;

此行为由5.17赋值和复合赋值运算符定义,第4节。

  

4如果左操作数是类类型,则类应完整。对类的对象的赋值由复制/移动赋值运算符(12.8,13.5.3)定义。

13.5.3转让,第1条。

  

1赋值运算符应由具有一个参数的非静态成员函数实现。因为如果没有由用户声明(12.8),则为类隐式声明了复制赋值运算符operator =,基类赋值运算符总是被派生类的复制赋值运算符隐藏。

功能

void operator =(int);

被选中

obj1 = 3;

根据过载规则。