8 c++ struct function overhead
我在下面试了一个例子:
typedef struct point
{
int x;
int y;
} point;
void cp(point p)
{
cout<<p.x<<endl;
cout<<p.y<<endl;
}
int main()
{
point p1;
p1.x=1;
p1.y=2;
cp(p1);
}
Run Code Online (Sandbox Code Playgroud)
打印出来的结果是:
1
2
Run Code Online (Sandbox Code Playgroud)
这是我的预期.我的问题是:参数p是否获得对象p1的完整副本?如果是这样,我想知道这是一个好习惯吗?(我假设当结构体积变大时,这将产生大量的复制开销).
CB *_*ley 18
是的,这没有任何问题,是的,p是完整的副本p1.我不会struct用两个int大的调用,但如果struct它变大,如果你不需要在函数体中改变它,你可以考虑通过const引用传递它:
void cp(const point& p)
{
// ...
}
Run Code Online (Sandbox Code Playgroud)
将结构作为参数传递没有任何问题.一切都是用C++中的值传递的,所以确实制作了完整的副本.
您在示例中提供的结构很小,因此如果按值传递它可能不是问题.但是,如果您使用更大的数据结构,您可能希望通过引用传递它.
但要注意,通过引用传递意味着如果修改函数内部的结构,将修改原始结构.在不修改结构的每种情况下,请务必使用const关键字.这将为您提供有关您的功能是否修改信息的即时信息.
您的示例可以通过以下方式修改为使用引用:
typedef struct point
{
int x;
int y;
} point;
void cp(const point& p) // You can know that cp doesn't modify your struct
{
cout<<p.x<<endl;
cout<<p.y<<endl;
}
void mod_point(point& p) // You can know that mod_points modifies your struct
{
p.x += 1;
p.y += 1;
}
int main()
{
point p1;
p1.x=1;
p1.y=2;
cp(p1);
mod_point(p1);
cp(p1); // will output 2 and 3
}
Run Code Online (Sandbox Code Playgroud)
在我回答你的问题之前(你会在本文末尾找到它),这里简要总结了你将参数传递给函数的可能性:
1.复制构造的对象(按值传递):
void cp(point p);
Run Code Online (Sandbox Code Playgroud)
这是按值传递的.point从point您传入的任何对象创建并复制构造临时对象cp.一旦执行离开cp函数,临时对象就会被销毁.
请注意,因为函数对传递给函数的任何内容的副本进行操作,所以您可以根据需要修改该本地point对象,不会影响调用者的原始对象.使用pass-by-value参数无法更改此行为.
2.对象的引用(pass-by-reference):
void cp(point& p);
Run Code Online (Sandbox Code Playgroud)
这是传递参考.传递给函数的实际对象在函数内部可用(并且可能需要修改).如果您不希望该函数能够更改传入的对象,请将参数声明为const point&:
void cp(const point& p);
Run Code Online (Sandbox Code Playgroud)
3.指向对象的指针(按引用传递):
void cp(point* p);
Run Code Online (Sandbox Code Playgroud)
这也是传递参考,有一些细微的差别.一个值得注意的区别是您可以将空指针传递给该函数.引用无法做到这一点,因为引用必须初始化,之后不能重新引用.- 与引用一样,如果要禁止cp更改传入point,请将其声明为const:
void cp(const point* p);
Run Code Online (Sandbox Code Playgroud)
按值传递参数本身并不是坏事.当然,存在复制构造昂贵的类型(例如,非常大或复杂的对象),或者其具有某些副作用(例如,具有std::auto_ptr)的类型.在这些情况下,你应该小心.否则,它只是C++的另一个特性,它具有完全合理的用途.