8

我在下面尝试了一个示例:

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 的完整副本?如果是这样,我想知道这是否是一个好习惯?(我假设当结构变大时,这会产生大量的复制开销)。

4

6 回答 6

18

是的,这没有什么问题,是p的,它是p1. 我不会struct用两个ints 来调用 a ,但是如果它struct确实变大了,并且如果你不需要在函数体中改变它,你可以考虑通过 const 引用传递它:

void cp(const point& p)
{
    // ...
}
于 2010-04-27T20:14:16.007 回答
8

将结构作为参数传递并没有错。在 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
}
于 2010-04-27T20:25:49.617 回答
6

在我回答你的问题之前(你可以在这篇文章的末尾找到它),这里是你将参数传递给函数的可能性的简要总结:


1. 复制构造的对象(按值传递):

void cp(point p);

这是按值传递。一个临时对象是从你传入point的任何对象创建和复制构造的。一旦执行离开函数,临时对象就会被销毁。pointcpcp

请注意,由于该函数对传递给该函数的任何内容的副本进行操作,因此您可以根据需要修改该本地point对象,调用者的原始对象不会受到影响。无法使用按值传递的参数来改变这种行为。


2. 对象引用(pass-by-reference):

void cp(point& p);

这是通过引用传递。传递给函数的实际对象在函数内部是可用的(并且可能会受到修改)。如果您不希望函数能够更改传入的对象,请将参数声明为const point&

void cp(const point& p);

3. 指向对象的指针(pass-by-reference):

void cp(point* p);

这也是通过引用传递的,有一些细微的差别。一个显着的区别是您可以将空指针传递给函数。这对于引用是不可能的,因为引用必须被初始化并且之后不能被重新安装。-- 与引用一样,如果您想禁止cp更改传入的point,请将其声明为 const:

void cp(const point* p);

回答你的问题:

值传递参数在任何方面都不是天生的坏事。当然,有些类型的复制构造成本很高(例如非常大或复杂的对象),或者它具有某些副作用(例如 with std::auto_ptr)。在这些情况下,您应该小心。否则,它只是 C++ 的另一个具有完全合理用途的特性。

于 2010-04-27T20:24:40.997 回答
1
void cp(point p){
}

按值获取

void cp(point *p){
}

通过参考得到它

就像任何其他数据变量一样。

在java中,情况是不同的。传递对象总是通过引用。

于 2010-04-27T20:15:44.663 回答
1

在您的情况下,点结构是“按值”传递的,意思是复制整个结构。对于大数据类型,这确实可能很慢。

您可以考虑通过引用传递对象

void cp(point& p) // p may be altered!

或者是 const 参考

void cp(const point& p) // p may not be altered!
于 2010-04-27T20:15:48.800 回答
1

查看避免按值传递对象的可能性。该对象不仅是“复制”的,而且是复制构造的。因此,如果您的对象由更多对象组成或派生,则这涉及调用复制构造函数和复制构造函数链。如果可能,通过引用传递。

void cp(point &p const) const {

    cout << p.x << endl;
    cout << p.y << endl;

}

于 2010-04-27T20:17:15.023 回答