C++ 复制构造函数是如何使用的,为什么它们很重要?
什么是复制构造函数C++ 复制构造函数是如何使用的,为什么它们很重要?,c++,C++,什么是复制构造函数 我们为什么要使用它们?如果我们这样做,有必要调用析构函数吗 复制构造函数之所以重要,原因与常规构造函数相同,那就是正确初始化构造的对象。构造并不总是琐碎的,从何处获取数据以及以何种形式获取数据并不重要——相同类的其他对象或一组更简单的参数 所以,复制构造函数是用来解决初始化常量字段之类的问题的,但当您使用指针时,也可以用来决定所指资源的所有权。您可能希望共享或复制数据 什么是复制构造函数? 引用C++11标准,§12.8/2: 如果类X的非模板构造函数的第一个参数类型为X&,
我们为什么要使用它们?如果我们这样做,有必要调用析构函数吗 复制构造函数之所以重要,原因与常规构造函数相同,那就是正确初始化构造的对象。构造并不总是琐碎的,从何处获取数据以及以何种形式获取数据并不重要——相同类的其他对象或一组更简单的参数 所以,复制构造函数是用来解决初始化常量字段之类的问题的,但当您使用指针时,也可以用来决定所指资源的所有权。您可能希望共享或复制数据 什么是复制构造函数? 引用C++11标准,§12.8/2: 如果类
X
的非模板构造函数的第一个参数类型为X&
,const X&
,则该类的非模板构造函数是副本构造函数,
volatile X&
或const volatile X&
,或者没有其他参数,或者没有其他所有参数
“有默认参数”
所以有4种不同的形式。其中最常用的是X const&
形式。这也是隐式复制构造函数的形式,如果没有为类声明复制构造函数,则生成该构造函数(如果可能)
复制构造函数用于将对象复制到类的新实例。默认复制构造函数执行成员级复制,这与仅复制位不同,也比复制位更安全。具体而言,复制构造函数或移动构造函数在逻辑上用于复制初始化,即使用=
符号的初始化
Some_type x = expression;
在某些情况下,编译器可以假设复制是复制构造函数所做的一切,而不管它实际做什么。逻辑上不必要的复制构造可以被删除,或者按照标准的说法,被省略。例如,如果上面的表达式是数字42,则可以使用该参数直接初始化x
,而不是使用该参数来构造临时变量并将其复制或移动到x
但是,即使这样做了,也不会使用复制构造函数,如果复制构造函数在优化之外会被使用,那么复制构造函数必须存在并且可以访问
C++11§12.2/1:
“即使临时对象的创建未经评估(第5条)
或以其他方式避免(12.8),应遵守所有语义限制,如同临时对象已被删除一样
已创建并随后销毁。”
有必要调用析构函数吗? Re“如果我们[使用复制构造函数],是否需要调用析构函数?” 一般不会 < > C++中的析构函数在对象超出范围时被自动调用,或者当它通过“代码>删除< /代码>被间接或直接销毁时被自动调用。唯一的例外是placement new,这是一个与复制构造函数无关的低级功能。虽然新的放置可能涉及复制构造
C++03和C++11复制构造函数之间的差异。 要理解C++03和C++11在副本构造函数方面的差异,您必须了解三个事实:
- 如果未声明副本构造函数,则会在可能的情况下生成它。因此,默认情况下,每个类都有一个复制构造函数。就在那里
- 访问与过载分辨率无关。
重载解析在所有成员函数之间进行选择,无论它们是否可访问。然后检查访问权限。在这一点上,您可能会收到一条关于调用不可访问函数的错误消息,尽管期望重载解析最好只能从可访问函数中选择 - 普通函数(或只是函数)比具有相同签名的函数模板的实例化更匹配
private
成员函数,尽管可以调用一个public
函数:
文件[access\u vs\u overload\u resolution.cpp]下面是一个普通函数胜过模板实例化的示例: 文件[function\u vs\u template.cpp]
使用旧的g++编译: [H:\dev\test\copy_construction] > \bin\MinGW_3_1\bin\g++ --version | find "++" g++ (GCC) 3.2.3 (mingw special 20030504-1) [H:\dev\test\copy_construction] > \bin\MinGW_3_1\bin\g++ -std=c++98 -pedantic template_versus_cc.cpp template_versus_cc.cpp: In function `int main()': template_versus_cc.cpp:4: `S::S(const S&)' is private template_versus_cc.cpp:19: within this context [H:\dev\test\copy_construction] > _ [H:\dev\test\copy\u构造] >\bin\MinGW_3_1\bin\g++--version | find“++” g++(GCC)3.2.3(mingw special 20030504-1) [H:\dev\test\copy\u构造] >\bin\MinGW\u 3\u 1\bin\g++-std=c++98-学究式模板与cc.cpp 函数“int main()”中的模板\u与\cc.cpp: 模板与cc.cpp:4:'S::S(const S&')是私有的 模板与cc.cpp:19:在此上下文中 [H:\dev\test\copy\u构造] > _ 根据C++03/C++98规则,编译器应该在第18行和第19行标记两个副本初始化,但只标记后者,在这方面表现为C++11编译器 <>这也是现代的G+4.4.2的原理以及Visual C++ 12。但是一个合格的C++03编译器必须诊断这两种初始化
Scott Meyers引用了两位C++闲人作为资料来源。不幸的是,这篇文章给人的印象是:(1)这都是关于C++11中的通用引用模板参数的,(2)g++中没有bug。如上所示,前者是错误的,而后者则是正确的。有一个bug,但随着标准的发展,使用C++11,g++行为现在符合要求了…为什么不在发布之前使用google?C中没有复制构造函数。那么为什么要标记这个问题[C]?你可能应该得到你自己的答案。副本当前选择了一个不正确的答案作为解决方案。此外,复制构造函数的概念在C++11中发生了微妙的变化,而重复的问题来自2010年。投票重开。@干杯,我不觉得这样更好吗
using One = char[1];
using Two = char[2];
auto foo( char const* ) -> One&;
auto foo( char const (&)[10] ) -> Two&;
auto bar( char const* ) -> One&;
template< int n >
auto bar( char const (&)[n] ) -> Two&;
#include <iostream>
auto main() -> int
{
using namespace std;
//cout << sizeof( foo( "Blah blah" ) ) << endl; //! Ambiguous
cout << sizeof( bar( "Blah blah" ) ) << endl; // "1"
}
class S
{
private:
S( S const& ); // No such.
public:
S() {}
template< class T >
S( T& ) {}
};
int main()
{
S sm;
S const sc;
S s1( sm ); // OK in C++11, template is better match.
S s2( sc ); //! Line 19. Copy constructor is selected, inaccessible.
}
[H:\dev\test\copy_construction]
> \bin\MinGW_3_1\bin\g++ --version | find "++"
g++ (GCC) 3.2.3 (mingw special 20030504-1)
[H:\dev\test\copy_construction]
> \bin\MinGW_3_1\bin\g++ -std=c++98 -pedantic template_versus_cc.cpp
template_versus_cc.cpp: In function `int main()':
template_versus_cc.cpp:4: `S::S(const S&)' is private
template_versus_cc.cpp:19: within this context
[H:\dev\test\copy_construction]
> _