请考虑以下代码:
#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 ++标准强制执行还是特定于编译器?有人能引用定义此行为的标准部分吗?
答案 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节。
13.5.3转让,第1条。4如果左操作数是类类型,则类应完整。对类的对象的赋值由复制/移动赋值运算符(12.8,13.5.3)定义。
1赋值运算符应由具有一个参数的非静态成员函数实现。因为如果没有由用户声明(12.8),则为类隐式声明了复制赋值运算符operator =,基类赋值运算符总是被派生类的复制赋值运算符隐藏。
功能
void operator =(int);
被选中
obj1 = 3;
根据过载规则。