私有类语法中的复制构造函数

Posted

技术标签:

【中文标题】私有类语法中的复制构造函数【英文标题】:Copy constructor in private class Syntax 【发布时间】:2015-04-30 11:35:00 【问题描述】:

2 小时后我将参加 C++ 考试,但我仍然想知道复制构造函数的语法。

到目前为止,我所理解的是,您将 CopyConstructor 置于私有状态,这样当某些函数或其他任何东西想要复制您的类时,它就无法工作,因为它无法访问私有变量。因此,您可以检查是否遗漏了任何只会进行浅拷贝的指针。

到目前为止一切顺利。

现在我读到的语法是

ClassName(const ClassName &)

我想知道为什么你有那个 & 和 const。仅仅 ClassName(ClassName) 就够了吗?

【问题讨论】:

您的实际问题与您帖子的第一部分完全无关。为什么要将任何其他函数中的参数作为 const 引用传递?同样的答案也适用于此。 您需要重新阅读您的介绍性教科书。不幸的是,这可能需要两个多小时。祝你考试顺利,下次记得复习。 @vsoftco ClassName(const ClassName &) 实际上与ClassName(ClassName) 不一样,因为过载。 知道了,虽然现在我测试了,似乎连声明都不OK,ideone.com/cuCq4q。 @Lanting 我知道,我首先认为声明它是合法的(而不是定义它)。 不确定否决票,这似乎是一个合理的问题。对于新手来说,函数参数会从相应的参数中复制构造出来并不是很明显,而且书籍通常不会详细介绍这种程度,尤其是在早期。 【参考方案1】:

来自 C++14 中的 [class.copy]/2:

X的非模板构造函数是一个复制构造函数,如果它的第一个参数是X&const X&volatile X&const volatile X&类型,并且要么没有其他参数,要么全部其他参数有默认参数。

因此,根据语言的定义,您的建议不会是复制构造函数。

事实上,根据 [class.copy]/6,您的建议是错误的:

如果类 X 的第一个参数的类型(可选 cv-qualified)X 并且没有其他参数或者所有其他参数都具有默认参数,则类 X 的构造函数声明是格式错误的。

【讨论】:

Foo(Foo);这样声明其实是编译时错误,我现在才发现。【参考方案2】:

为了通过值传递某些东西,您需要能够对其进行复制。我们如何制作副本?当然是复制构造函数!所以如果我们定义像ClassName(ClassName)这样的拷贝构造函数,我们传入一个ClassName,调用拷贝构造函数,它调用拷贝构造函数……

这会导致无限递归;不是一种非常合理的复制对象的方式。这就是我们通过引用传递的原因:所以我们不需要制作任何其他副本。 const 存在是因为复制对象不应该修改它,否则你会得到像 auto_ptr 这样可怕的东西。

此外,对于 C++11,最好使用 =delete 来阻止人们复制您的类,而不是将复制构造函数设为私有:

ClassName (const Classname&) = delete;

【讨论】:

【参考方案3】:

const 表示您还可以复制一个常量类(并且您承诺不会修改您正在复制的类。

& 符号& 表示你的复制构造函数引用了它试图复制的东西(没有& 符号它会得到它的副本,这是不可能的,因为我们实际上是在尝试复制)。

【讨论】:

【参考方案4】:

语法f(Classname) 表示复制参数,而f(const Classname&) 引用参数。

然而,复制提供给复制构造函数的参数会非常糟糕,它应该定义如何制作这样的副本......

【讨论】:

【参考方案5】:

我想知道为什么你有那个 & 和 const 在那里

& 表示要复制的对象是通过引用传递的。 const 表示引用不能用来修改它;这是您在复制时所期望的。

ClassName(ClassName) 还不够吗?

这意味着对象是按值传递的。为此,它必须被复制。要复制它,您必须调用复制构造函数。为此,您必须按值传递对象。为此,它必须被复制。以此类推。

所以不,复制构造函数不能按值获取参数。

【讨论】:

不知何故,“常量意味着引用只能用于修改它”这句话令人困惑。 const 避免了传递的引用被复制构造函数修改。

以上是关于私有类语法中的复制构造函数的主要内容,如果未能解决你的问题,请参考以下文章

通过定义默认私有构造函数使类不可继承

私有构造函数有啥作用? [复制]

抽象类中的私有构造函数

声明构造函数私有和 =delete 有啥区别?

内部类中的私有构造函数在外部类中初始化

我们啥时候需要 C++ 中的私有构造函数?