为什么我们在复制构造函数的参数中要使用引用而不是指针?

5
为什么我们在拷贝构造函数的参数中要使用引用而不是指针?这个问题在面试中被问到。我回答了以下几点:
  1. 引用不能为NULL。
  2. 如果我们使用指针,那么它就不是一个拷贝构造函数。
  3. 标准规定如此(第12.8.2节)。
但面试官并不满意。他说这与继承和虚函数有关。我需要一些帮助或相关观点,以便能够考虑到那个方向的答案。

6
我认为你的面试官正在经历邓宁-克鲁格效应。 - Brian Bi
相关:为什么在C++中复制构造函数应该通过引用接受其参数?。顺便说一下,你的理由是正确的。我不知道其他任何继承或多态性方面的注意事项。实际上,指针不能反映对象,因为它们只是地址。在这方面,引用和指针之间没有比较。 - iammilind
除了不能合法地传递“NULL”之外,没有任何理由使指针比引用更可取。你是正确的,面试官是错误的。 - Sergey Kalinichenko
3
他也许是在问为什么标准要这样定义? - Benjamin Lindley
1
最重要的引用驱动因素是从临时对象创建对象或通过值传递临时对象到函数,例如 f(a+b) -- 其中a和b是类A的对象,而fA::f(A obj) - g-217
显示剩余3条评论
2个回答

2
你的面试官错了,而你是正确的。
你回答中最重要的部分是第二点和第三点(实质上是相同的观点,但措辞不同):因为标准规定如此见12.8.2):

如果类X的非模板构造函数的第一个参数是类型为X&const X&volatile X&const volatile X&的引用,并且没有其他参数或者所有其他参数都有默认值(...),则它是类X的拷贝构造函数。

我们使用引用而不是指针因为标准规定如此。否则就不是拷贝构造函数。
当涉及到继承和虚函数时,引用可以做到指针所能做的一切。
你所提供的唯一另一个理由,正如Gautam Jha在评论中指出的那样,就是引用允许你从临时对象中进行复制。

2
你的观点看起来很合理,我无法想象出你的面试官希望从你那里听到什么。
但据我所知,让复制构造函数和赋值运算符具有统一的语法是Stroustrup引入引用的重要原因之一。例如,假设我们在C++中没有引用,并且我们想进行一些复制构造,通过指针传递参数:
class MyClass {
    // Copy ctor and assignment operator are declared
    // like this in our referenceless "C with classes" language:
    MyClass(const MyClass* const);
    MyClass* operator=(const MyClass* const);
};

MyClass a, b, c;

//Let's copy-construct:
MyClass d = &a; // Dereferencing looks ugly.

//Let's assign:
a = &b; // Dereferencing again.

// Even worse example:
a = b = c = &d; // Only the last variable should be dereferenced.
a = b = &c; // Awfully inhomogeneous code.
/*
The above line is equivalent to a = (b = &c),
where (b = &c) returns a pointer, so we don't need to
dereference the value passed to assignment operator of a.
*/

很明显,这不是内置类型的工作方式:

int a, b, c;
int d = a;
a = b = c = d;

因此,引入了引用来解决这些不均匀性。

更新

有关此观点的权威证明,请参阅Stroustrup的《C++设计与演化》第3.7节。不幸的是,我没有这本书的英文版,但章节的第一句话是:

引入引用主要是为了支持运算符重载。

在接下来的几页中,Stroustrup深入探讨了这个主题。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接