考虑以下情况
class Integer
{
long long n;
public:
Integer(long long i):n(i){}
Integer(){cout<<"constructor";}
void print()
{
cout<<n<<endl;
}
Integer(const Integer &a){cout<<"copy constructor"<<" "<<a.n<<endl;}
Integer operator+(Integer b);
};
Integer Integer:: operator+(Integer b)
{
this->n = this->n + b.n;
return *this;
}
int main()
{
// your code goes here
Integer a(5);
Integer b(6);
Integer c(a+b);//line 1
return 0;
}
如果a+b
是临时的,那么我理解不会调用复制构造函数。但a+b
不会返回临时。
我得到的输出是
copy constructor 6 //this is because Integer object is passed as value to operator+
copy constructor -5232903157125162015 //this is when object is returned by value from operator+
我认为在使用a+b
初始化c
时应该再打一次电话。大多数相关问题与返回值优化有关,但i
无法将RVO与此相关联。
答案 0 :(得分:2)
您说 a+b
不会返回临时。错误。 a+b
(即使它更改a
肯定会误导未来的读者......)会返回a
的临时副本,因为它被声明为返回Integer
而不是引用(Integer&
)。
所以这是发生的事情:
Integer a(5); // creates an integer from int 5
Integer b(6); // creates an integer from int 6
Integer c(a+b); /* first creates a temp using copy ctor from b
updates a
creates a temp copy of the result
should create an integer by copy of the result (elided)
destroys the temporary created from b
*/
return 0; // destroys c, b, a
BTW:您忘记在副本中初始化n
- 它应该是:
Integer(const Integer &a):n(a.n) {cout<<"copy constructor"<<" "<<a.n<<endl;}
答案 1 :(得分:1)
您正在见证构造函数的copy ellission。
当无名的临时(未绑定到任何引用)将被移动或复制到相同类型的对象(忽略顶级cv资格)时,将省略复制/移动。构造临时值时,它将直接构建在存储器中,否则将被移动或复制到该存储器中。当无名临时是return语句的参数时,copy elision的这个变体称为RVO,“返回值优化”。
要查看预期的输出(不要忽略构造函数),请使用-fno-elide-constructors
中的gcc
选项。
修改强>
正如我对你的问题Integer:: operator+
的评论中所提到的那样。此外,如其他答案中所述,您的复制构造函数不会对成员进行初始化,从而导致未定义的行为。
答案 2 :(得分:1)
要回答您的问题,复制构造函数永远不会复制任何内容,X.GridPanel()
.Cls("x-grid-custom twelve")
.ID("gridIRPAlerts")
.Scroll(ScrollMode.Both)
.AutoScroll(true)
.MaxHeight(240)
.EnableColumnHide(false)
.ColumnLines(true)
.Store(
X.Store()
.RemoteFilter(true)
.Model(
X.Model()
.Fields(
// Approx 15 ModelFields...
)
)
.Proxy(
Html.X().AjaxProxy()
.Url(Url.Action("GetAllIRPConfirmData", "CommonWidget")).Timeout(500000) //added timeout as record count is too big
.ActionMethods(actions =>
{
actions.Read = HttpMethod.POST;
})
.Reader(Html.X().JsonReader().Root("data"))
.Listeners(l => l.Exception.Handler = "Error()")
)
)
.EmptyText("No IRP Alerts Available.")
.ColumnModel(
X.Column().DataIndex("Desc").ID("IRP_IDForHeader").Text("IRP").Flex(5),
X.Column().DataIndex("Channel").Text("Channel").Flex(2),
X.Column().DataIndex("PType").Text("My column").Flex(2),
X.NumberColumn().DataIndex("Price").Text("New Price").Format("0.00").Flex(2).Align(Alignment.Right),
X.DateColumn().DataIndex("Effective_Date").Text("Effective Date").Format(PRUtil.GetDateFormat()).Flex(3).Align(Alignment.Center)
)
运算符也不会正确重载。此外,默认构造函数为+
类留下了未初始化的成员,可能导致未定义的行为(不是100%),这可能会导致一些问题。
所以会发生什么,因为复制构造函数实际上从未将值复制到Integer
的{{1}}成员,调用默认构造函数,并且std :: cout显示位于n
的&#39; a.n&#39;如果没有初始化,可以是任何东西。
This website对于超载运营商来说是好的,如果不完善的话。
试试这个。
*this
答案 3 :(得分:0)
它具有正确数量的复制ctor调用:
第一个是b
,因为operator+(Integer b)
按值接受Integer
。
第二个是由c
结果创建的operator+
。
根据标准,可能会有第3次呼叫:return *this
可能已创建临时,稍后会将其复制到c
。但实际上它总是被省略。您可以在gcc&amp; clang中关闭此省略,但您无法在MSVC中将其关闭。