C++中的困惑

Mic*_*ync 5 c++ parameter-passing pass-by-reference

我是C++的新手,我正在学习它.我有几个问题..

  1. void DoSomething(const Foo&foo)void DoSomething(Foo foo)之间有什么区别如果我们没有指定&那么Foo的实例将通过值(不是引用)传递.除了在编译时没有检查外,它与const +&在参数中是一样的.那么,为什么在没有&和const的情况下让const +&成为参数的最佳实践?

    在C#中,传递对象是"通过引用",但似乎不是在C++中.

  2. 我正在阅读的书中说成员函数通过引用传递隐式参数.

    任何人都可以给我隐含参数的样本和参考?我知道如果我们想通过引用传递对象,我们需要使用&(例如Foo(Person&p))但是C++如何通过引用传递对象的隐式参数?我读到C++中的隐式参数就像Contructor(string str):strMemberVariable(str){} ...

  3. 数组是C++中唯一通过引用传递的数组吗?

  4. 为什么我不能在Foo类中使用Foo fInstance

例:

class Foo {

public:    
    Foo() { }

    Foo(const Foo& f) : fInstance(f) {   }  

    Foo fInstance;      
};
Run Code Online (Sandbox Code Playgroud)

提前致谢.

Mat*_* M. 10

1 void DoSomething(const Foo&foo)和void DoSomething(Foo foo)?之间有什么区别?如果我们没有指定&那么实例Foo将通过值(不是引用)传递.除了在编译时没有检查外,它与const +&在参数中是一样的.那么,为什么在没有&和const的情况下让const +&成为参数的最佳实践?

在C#中,传递对象是"通过引用",但似乎不是在C++中.

根据重要性,有几个不同之处:

  • 如果Foo无法复制对象,则需要通过引用传递它
  • 如果对象Foo是基类,则应通过引用获取它,以便用户可以使用派生类调用函数
  • 即使您持有const对它的引用,实际对象的值也可能会更改
  • 效率,复制用户类型可能很昂贵,但编译器可能足够聪明,可以解决这个问题......

2我正在阅读的书中说成员函数通过引用传递隐含参数.

任何人都可以给我隐含参数的样本和参考?我知道如果我们想通过引用传递对象,我们需要使用&(例如Foo(Person&p))但是C++如何通过引用传递对象的隐式参数?我读到C++中的隐式参数就像Contructor(string str):strMemberVariable(str){} ...

通过隐式参数你应该理解this,那就是对象本身.它通过引用有效传递,因为您可以在成员函数中修改其状态.

下面Konrad的注释:注意它this本身不是通过引用传递的,this是对象的引用(指针),但是通过值传递.您无法根据需要更改对象的内存地址;)

3数组是C++中唯一通过引用传递的数组吗?

他们不是.您将看到数组元素的更改,但数组(结构)不会更改.

以下FredOverflow是一个例子:

void fun(int* p, size_t size);

int main(int argc, char* argv[])
{
  int array[15];
  fun(array, 15);
}
Run Code Online (Sandbox Code Playgroud)

我们不知道是什么fun,它可能会改变一些元素array,但无论它的动作如何,array都将保持15个整数的数组:内容改变,结构不改变.

因此,要改变array我们需要另一个声明:

void changer(int*& array, size_t& size);
Run Code Online (Sandbox Code Playgroud)

这样我们就可以改变内容和结构(并传回新的大小).当然,我们只能使用动态分配的数组调用此函数.

4为什么我不能在Foo类中使用Foo fInstance?

因为那是无限递归.从编译器的角度考虑它,并尝试猜测它的大小Foo.大小Foo是其属性大小的总和,可能还有一些填充和类型信息.此外,对象大小至少1是可以解决的.那么,如果Foo有一个Foo,它的大小是多少:)?

通常的解决方案是使用智能指针:

class Foo
{
public:

private:
  std::unique_ptr<Foo> mInstance;
};
Run Code Online (Sandbox Code Playgroud)

因为指针的大小不依赖于指向的对象的大小,所以这里没有递归:)

  • @ bk1e:是当然的,但"参考",在C具有非常明显的,固定的含义++和指针和引用是*不*同样的事情,并且既不是指针传递(由值),并且通过引用传递. (2认同)

Kon*_*lph 7

由于这里存在许多误解和彻头彻尾的错误答案,这是我试图纠正这个问题:

void DoSomething(const Foo& foo)和之间的区别是什么?void DoSomething(Foo foo)?

正如其他人所说,第二个代码需要一个副本(通常调用复制构造函数Foo).

那么,为什么在没有&和const的情况下让const +&成为参数的最佳实践?

其他人已经回答了一些特殊的问题(例如运行时多态性).这并不能解释为什么它成为最佳实践.这样做的原因很简单,丑:因为它是幅度更高效.想象一下,将矢量或字符串传递给另一个方法 - 或者基本上只是传递任何大数据结构.复制它的成本通常很大,并且可能经常在代码中调用方法 - 实际上,通常会经常调用方法,否则代码设计得很糟糕.

另一方面,当您将对象作为const引用传递时,这是通过指针在内部(通常)实现的.在所有体系结构中,始终可以有效地复制指针.

我正在阅读的书中说成员函数通过引用传递隐式参数.

我觉得这本书错了.类的成员函数隐式地传递一个this引用当前对象的指针.但是,这是一个指针,C++禁止更改它.它没有理由通过引用传递.

数组是C++中唯一通过引用传递的数组吗?

在C++中很少传递数组 - 它们通常作为指针传递:

void foo(int[] x) { … }
Run Code Online (Sandbox Code Playgroud)

实际上是一样的

void foo(int* x) { … }
Run Code Online (Sandbox Code Playgroud)

编译器将这两个声明视为相同.当您尝试调用这些方法中的任何一个并将其传递给数组时x,C++将隐式地将数组转换为指向其第一个元素的指针 - 这称为"衰减".所以,foo(x)将成为foo(&x[0]).

然而,阵列可以改为按引用传递的,如果他们的指定大小:

void foo(int (&x)[4]);
Run Code Online (Sandbox Code Playgroud)

但是,再一次,您明确声明数组是通过引用传递的.

  • `void foo(int x [4])`与`void foo(int x [])`和`void foo(int*x)`完全相同.大小被忽略了.数组永远不会通过引用隐式传递.你应该将最后一部分改为`void foo(int(&x)[4])`. (3认同)