将struct对象作为参数传递到C ++中的函数是一个好习惯吗?
题
我在下面尝试了一个示例:
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);
}
结果是:
1
2
这就是我所期望的。我的问题是:参数P是否获取对象P1的完整副本?如果是这样,我想知道这是否是一个好习惯? (我假设当结构大小时,这将创建大量的副本开销)。
解决方案
将结构作为参数传递没有错。一切都按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
}
其他提示
是的,这没有错,是的, p
是完整的副本 p1
. 。我不会叫 struct
有两个 int
很大,但是如果 struct
确实变大了,如果您不需要在功能体中进行更改,则可以考虑通过const参考将其传递:
void cp(const point& p)
{
// ...
}
在我回答您的问题之前 (您在这篇文章的结尾找到了),这是您将参数传递给函数的可能性的简要摘要:
1.复制构造的对象(逐个价值):
void cp(point p);
这是逐个价值。临时 point
对象是从任何东西创建和复制构造的 point
您传递的对象 cp
. 。一旦执行离开 cp
功能,临时对象被破坏。
请注意,由于该功能在传递给该功能的任何内容的副本上运行,因此您可以修改该本地 point
对象尽可能多地,呼叫者的原始对象不会受到影响。没有办法通过通过传递参数来改变这种行为。
2.参考对象(通过转文):
void cp(point& p);
这是通过引用。传递给该函数的实际对象可在功能内部使用(并有可能受到修改)。如果您不希望函数能够更改传递对象,请将参数声明为 const point&
:
void cp(const point& p);
3.指向对象的指针(逐一引用):
void cp(point* p);
这也是通过引用的传递,存在一些细微的差异。一个值得注意的区别是,您可以将零指针传递给该功能。参考是不可能的,因为参考 必须 初始化,之后无法重新安置。 - 与参考一样,如果您想禁止 cp
从更改传递 point
, ,将其声明为const:
void cp(const point* p);
回答您的问题:
通过任何方式,通过逐个价值参数本质上都不是不好的。当然,在某些类型的类型中,复制构造价格昂贵(例如,非常大或复杂的对象),或者具有一定的副作用(例如 std::auto_ptr
)。在这些情况下,您应该小心。否则,它只是C ++的另一个功能,具有完全合理的用途。
void cp(point p){
}
凭价值获取
void cp(point *p){
}
通过引用获取
就像任何其他数据变量一样。
在Java中,情况不同。传递对象始终通过参考。
在您的情况下,点结构是“按值”传递的,含义是复制整个结构。对于大数据类型,这确实可以很慢。
您可以考虑通过参考传递对象
void cp(point& p) // p may be altered!
或成为const参考
void cp(const point& p) // p may not be altered!
请参阅避免按值传递对象的可能性。该对象不仅是“复制”,而且是构造的复制。因此,这涉及调用复制构造函数和复制构造函数,如果您的对象是由更多对象组成或得出的。如果可能的话,请通过参考。
void cp(point&p const)const {
cout << p.x << endl;
cout << p.y << endl;
}