#include <iostream>
using namespace std;
class A
{
public:
A()
{
cout << "A()\n";
}
A(const A& other)
{
cout << "A(const A& other)\n";
}
~A()
{
cout << "~A()\n";
}
};
A fun()
{
//A a;
//return a;
return A();
}
int main()
{
A b = fun();
}
返回局部变量a的话, 会调用一次构造, 一次拷贝构造, 并没有再生成一个中间临时变量
返回A()应该就是RVO优化了, 只需一个构造函数
我想问的是, 为什么int型变量就会产生一个中间临时变量, 而类对象就没了呢
也是优化吗
23 个解决方案
#1
这是个秘密、、、、一个不为人知的秘密、、、、
#2
int会有一个副本,对于类,会有浅复制和深复制之分,你可以写自己的拷贝方法,去实习深复制
#3
我问的是int有副本, 类对象怎么没副本了
#4
这个问题没法具体回答你,类里可能有非常复杂的组成,没必要默认就创建副本,浪费不必要的内存,特别市里面的指针类型,副本就要重新开辟空间,完全没有必要,除非你需要,自己写
#5
应该是优化了
#6
同意楼上的,应该是优化了,而int 内置类型没有优化的必要。
#7
int会有一个副本?何处此言?
如果返回值为int的话,应该就是通过eax寄存器吧?
#8
是,eax用作返回值
#9
A fun()
{
return A();
}
会被编译器处理为:
void fun(A *__result)//编译器需要先为返回值分配空间,然后将该空间的地址传递给func, 然后以该地址为this指针构造对象
{
__result->A::A();//在返回值的地址上执行构造函数
}
对于如下调用:
A a = fun();
//先为a分配空间,然后将该空间的地址传递给fun
void fun(&a)
{
&a->A::A();//在a的空间上直接调用构造函数将a构造
}
而如下调用:
fun();
则是先分配一个临时的返回值空间,
A tmp;//注意,编译器在这里只是分配空间,并不调用构造函数,
然后
void fun(&tmp)
{
&tmp->A::A();//在tmp的空间上直接调用构造函数将tmp构造
}
然后,在函数调用结束后tmp又被析构
{
return A();
}
会被编译器处理为:
void fun(A *__result)//编译器需要先为返回值分配空间,然后将该空间的地址传递给func, 然后以该地址为this指针构造对象
{
__result->A::A();//在返回值的地址上执行构造函数
}
对于如下调用:
A a = fun();
//先为a分配空间,然后将该空间的地址传递给fun
void fun(&a)
{
&a->A::A();//在a的空间上直接调用构造函数将a构造
}
而如下调用:
fun();
则是先分配一个临时的返回值空间,
A tmp;//注意,编译器在这里只是分配空间,并不调用构造函数,
然后
void fun(&tmp)
{
&tmp->A::A();//在tmp的空间上直接调用构造函数将tmp构造
}
然后,在函数调用结束后tmp又被析构
#10
这个就是返回值优化,分为具名返回值优化和匿名返回值优化,你这个属于后者。
#11
int时的eax是中间变量,寄存器就是来传值的值给等号右边,别和对象情况混在一起,对象是把左边的地址直接传进函数在函数内直接构造左边,ALT+8跟踪一遍就妥了~!
#12
when a temporary class object that has not been bound to a reference (12.2) would be copied to a class
object with the same cv-unqualified type, the copy operation can be omitted by constructing the temporary
object directly into the target of the omitted copy
object with the same cv-unqualified type, the copy operation can be omitted by constructing the temporary
object directly into the target of the omitted copy
#13
回9楼
你的意思是说
A fun()
{
A a;
return a;
}
当A b = fun()时就将b用a拷贝构造
当fun()时就生成一个tmp对象用a来拷贝构造吗
你的意思是说
A fun()
{
A a;
return a;
}
当A b = fun()时就将b用a拷贝构造
当fun()时就生成一个tmp对象用a来拷贝构造吗
#14
纠正下!!eax“不”是中间变量
#15
in a return statement in a function with a class return type, when the expression is the name of a
non-volatile automatic object with the same cv-unqualified type as the function return type, the copy
operation can be omitted by constructing the automatic object directly into the function’s return value
non-volatile automatic object with the same cv-unqualified type as the function return type, the copy
operation can be omitted by constructing the automatic object directly into the function’s return value
#16
A fun1()
{
00413620 push ebp
00413621 mov ebp,esp
00413623 sub esp,0CCh
00413629 push ebx
0041362A push esi
0041362B push edi
0041362C lea edi,[ebp-0CCh]
00413632 mov ecx,33h
00413637 mov eax,0CCCCCCCCh
0041363C rep stos dword ptr es:[edi]
0041363E mov dword ptr [ebp-0C8h],0
//A a;
//return a;
return A();
00413648 mov ecx,dword ptr [ebp+8]
0041364B call A::A (411703h) //在&b上直接构造
00413650 mov eax,dword ptr [ebp-0C8h]
00413656 or eax,1
00413659 mov dword ptr [ebp-0C8h],eax
0041365F mov eax,dword ptr [ebp+8]
}
#17
但是如果有if 条件 return obj1; else return obj2;这样的语句,优化就会被阻止
#18
看过《Effective C++》木有?
看过《C++ 编程思想》木有?
好像都有讲。
看过《C++ 编程思想》木有?
好像都有讲。
#19
多写楼上几位指教
不过我想可能有的人把我问的东西搞错了
我要问的是
A fun()
{
A a;
return a;
}
int fun()
{
int a;
return a;
}
区别所在
不过我想可能有的人把我问的东西搞错了
我要问的是
A fun()
{
A a;
return a;
}
int fun()
{
int a;
return a;
}
区别所在
#20
这种情况下,如果编译器实施具名返回值优化的话,会被处理为如下:
void fun(A *__result)
{
__result->A::A();//用__result来代替局部对象a,避免了拷贝构造函数的调用
}
如果没有具名返回值优化,会被处理为如下,
void fun(A *__result)
{
A a;
__result->A::(a);//这里调用拷贝构造函数
}
《深度探索C++对象模型》这本书上有详细解释,楼主不妨看下,
#21
回20楼
意思是开了具名返回值优化
A fun()
{
A a;
return a;
}
A b = fun();
a已经不调构造函数了吗
只是b调用一次构造函数?
意思是开了具名返回值优化
A fun()
{
A a;
return a;
}
A b = fun();
a已经不调构造函数了吗
只是b调用一次构造函数?
#22
int fun()
{
int a;
return a;
}
最后的返回语句return a;
编译器只需要把a的值mov到eax寄存器中就完成了返回值的返回
而
A fun()
{
A a;
return a;
}
编译器必须在某处先开辟一个空间用于保存返回值对象,然后将该空间的地址传递给fun函数
在函数fun的return语句处安插语句将返回值构造出来
#23
恩,是的
DEV C++下面就有这个优化了
#1
这是个秘密、、、、一个不为人知的秘密、、、、
#2
int会有一个副本,对于类,会有浅复制和深复制之分,你可以写自己的拷贝方法,去实习深复制
#3
我问的是int有副本, 类对象怎么没副本了
#4
这个问题没法具体回答你,类里可能有非常复杂的组成,没必要默认就创建副本,浪费不必要的内存,特别市里面的指针类型,副本就要重新开辟空间,完全没有必要,除非你需要,自己写
#5
应该是优化了
#6
同意楼上的,应该是优化了,而int 内置类型没有优化的必要。
#7
int会有一个副本?何处此言?
如果返回值为int的话,应该就是通过eax寄存器吧?
#8
是,eax用作返回值
#9
A fun()
{
return A();
}
会被编译器处理为:
void fun(A *__result)//编译器需要先为返回值分配空间,然后将该空间的地址传递给func, 然后以该地址为this指针构造对象
{
__result->A::A();//在返回值的地址上执行构造函数
}
对于如下调用:
A a = fun();
//先为a分配空间,然后将该空间的地址传递给fun
void fun(&a)
{
&a->A::A();//在a的空间上直接调用构造函数将a构造
}
而如下调用:
fun();
则是先分配一个临时的返回值空间,
A tmp;//注意,编译器在这里只是分配空间,并不调用构造函数,
然后
void fun(&tmp)
{
&tmp->A::A();//在tmp的空间上直接调用构造函数将tmp构造
}
然后,在函数调用结束后tmp又被析构
{
return A();
}
会被编译器处理为:
void fun(A *__result)//编译器需要先为返回值分配空间,然后将该空间的地址传递给func, 然后以该地址为this指针构造对象
{
__result->A::A();//在返回值的地址上执行构造函数
}
对于如下调用:
A a = fun();
//先为a分配空间,然后将该空间的地址传递给fun
void fun(&a)
{
&a->A::A();//在a的空间上直接调用构造函数将a构造
}
而如下调用:
fun();
则是先分配一个临时的返回值空间,
A tmp;//注意,编译器在这里只是分配空间,并不调用构造函数,
然后
void fun(&tmp)
{
&tmp->A::A();//在tmp的空间上直接调用构造函数将tmp构造
}
然后,在函数调用结束后tmp又被析构
#10
这个就是返回值优化,分为具名返回值优化和匿名返回值优化,你这个属于后者。
#11
int时的eax是中间变量,寄存器就是来传值的值给等号右边,别和对象情况混在一起,对象是把左边的地址直接传进函数在函数内直接构造左边,ALT+8跟踪一遍就妥了~!
#12
when a temporary class object that has not been bound to a reference (12.2) would be copied to a class
object with the same cv-unqualified type, the copy operation can be omitted by constructing the temporary
object directly into the target of the omitted copy
object with the same cv-unqualified type, the copy operation can be omitted by constructing the temporary
object directly into the target of the omitted copy
#13
回9楼
你的意思是说
A fun()
{
A a;
return a;
}
当A b = fun()时就将b用a拷贝构造
当fun()时就生成一个tmp对象用a来拷贝构造吗
你的意思是说
A fun()
{
A a;
return a;
}
当A b = fun()时就将b用a拷贝构造
当fun()时就生成一个tmp对象用a来拷贝构造吗
#14
纠正下!!eax“不”是中间变量
#15
in a return statement in a function with a class return type, when the expression is the name of a
non-volatile automatic object with the same cv-unqualified type as the function return type, the copy
operation can be omitted by constructing the automatic object directly into the function’s return value
non-volatile automatic object with the same cv-unqualified type as the function return type, the copy
operation can be omitted by constructing the automatic object directly into the function’s return value
#16
A fun1()
{
00413620 push ebp
00413621 mov ebp,esp
00413623 sub esp,0CCh
00413629 push ebx
0041362A push esi
0041362B push edi
0041362C lea edi,[ebp-0CCh]
00413632 mov ecx,33h
00413637 mov eax,0CCCCCCCCh
0041363C rep stos dword ptr es:[edi]
0041363E mov dword ptr [ebp-0C8h],0
//A a;
//return a;
return A();
00413648 mov ecx,dword ptr [ebp+8]
0041364B call A::A (411703h) //在&b上直接构造
00413650 mov eax,dword ptr [ebp-0C8h]
00413656 or eax,1
00413659 mov dword ptr [ebp-0C8h],eax
0041365F mov eax,dword ptr [ebp+8]
}
#17
但是如果有if 条件 return obj1; else return obj2;这样的语句,优化就会被阻止
#18
看过《Effective C++》木有?
看过《C++ 编程思想》木有?
好像都有讲。
看过《C++ 编程思想》木有?
好像都有讲。
#19
多写楼上几位指教
不过我想可能有的人把我问的东西搞错了
我要问的是
A fun()
{
A a;
return a;
}
int fun()
{
int a;
return a;
}
区别所在
不过我想可能有的人把我问的东西搞错了
我要问的是
A fun()
{
A a;
return a;
}
int fun()
{
int a;
return a;
}
区别所在
#20
这种情况下,如果编译器实施具名返回值优化的话,会被处理为如下:
void fun(A *__result)
{
__result->A::A();//用__result来代替局部对象a,避免了拷贝构造函数的调用
}
如果没有具名返回值优化,会被处理为如下,
void fun(A *__result)
{
A a;
__result->A::(a);//这里调用拷贝构造函数
}
《深度探索C++对象模型》这本书上有详细解释,楼主不妨看下,
#21
回20楼
意思是开了具名返回值优化
A fun()
{
A a;
return a;
}
A b = fun();
a已经不调构造函数了吗
只是b调用一次构造函数?
意思是开了具名返回值优化
A fun()
{
A a;
return a;
}
A b = fun();
a已经不调构造函数了吗
只是b调用一次构造函数?
#22
int fun()
{
int a;
return a;
}
最后的返回语句return a;
编译器只需要把a的值mov到eax寄存器中就完成了返回值的返回
而
A fun()
{
A a;
return a;
}
编译器必须在某处先开辟一个空间用于保存返回值对象,然后将该空间的地址传递给fun函数
在函数fun的return语句处安插语句将返回值构造出来
#23
恩,是的
DEV C++下面就有这个优化了