值类型(现代C++)
默认情况下选件 C++ 类是值类型。 本主题提供值类型表示概述和问题与其使用相关。
值用于. 引用类型
默认情况下,如 C++ 选件类是值类型。 他们可以指定引用类型,使得多态行为支持面向对象的编程方法。 值类型从内存的角度有时会看到,并且窗体控件,而引用类型是有关基类和虚函数多态目的。 默认情况下,值类型 copyable,这意味着始终具有复制构造函数和复制赋值运算符。 对于引用类型,可使选件类非 copyable (请禁用复制构造函数和复制赋值运算符) 并使用虚拟析构函数,支持其既定多态性。 值类型也是有关目录,那么,当将其复制时,始终提供了两个独立的值可以单独修改。 引用类型是有关标识–它是哪种类型的对象? 因此,“引用类型”也称为“多态类型”。
如果事实需要一个类似于引用的类型 (基类,虚函数),如下面的代码中,的 MyRefType 选件类所示需要显式禁用复制。
// cl /EHsc /nologo /W4
class MyRefType {
private:
MyRefType & operator=(const MyRefType &);
MyRefType(const MyRefType &);
public:
MyRefType () {}
};
int main()
{
MyRefType Data1, Data2;
// ...
Data1 = Data2;
}
编译上面的代码产生以下错误:
值类型和移动性能
复制赋值开销避免使用的是由于新副本优化。 例如,那么,当您插入到字符串元矢量的一个字符串,则会变为上不进行复制的重新分配,因此,只有移动,即使它导致该矢量的增大。 这同样适用于其他操作,例如对两个非常大的对象的添加操作。 如何使这些值操作优化? 在某些 C++ 编译器,编译器将隐式启用此您的,这与复制构造函数可由编译器自动生成。 但是,在 Visual C++ 中,您的选件类需要“选择”中通过声明移动分配和构造函数在类定义中。 这种状态的使用二进制文件" and "符 (&& %) rvalue 引用在适当的成员函数声明和定义移动构造函数并移动分配方法。 您还需要正确的代码“窃取胆量”error 源对象插入。
如何决定是否需要启用的移动? 如果已经知道需要启用的复制构造,您可能希望启用的移动,如果它比一个多层次复制可以节省。 但是,因此,如果您知道需要将支持,它不一定表示要启用的副本。 此后用例称为“移动类型”。 一个示例已经在标准库中为 unique_ptr。 作为旁注,旧 auto_ptr 已弃用并将其 unique_ptr 替换精确因不移动语义支持在 C++ 的早期版本。
使用移动语义可以返回值或插入到元。 移动是复制的优化。 对堆分配的需要作为工作区域。 考虑以下伪代码:
#include <set>
#include <vector>
#include <string>
using namespace std;
//...
set<widget> LoadHugeData() {
set<widget> ret;
// ... load data from disk and populate ret
return ret;
}
//...
widgets = LoadHugeData(); // efficient, no deep copy
vector<string> v = IfIHadAMillionStrings();
v.insert( begin(v)+v.size()/2, "scott" ); // efficient, no deep copy-shuffle
v.insert( begin(v)+v.size()/2, "Andrei" ); // (just 1M ptr/len assignments)
//...
HugeMatrix operator+(const HugeMatrix& , const HugeMatrix& );
HugeMatrix operator+(const HugeMatrix& , HugeMatrix&&);
HugeMatrix operator+( HugeMatrix&&, const HugeMatrix& );
HugeMatrix operator+( HugeMatrix&&, HugeMatrix&&);
//...
hm5 = hm1+hm2+hm3+hm4+hm5; // efficient, no extra copies
启用相应的值类型的移动
对于移动超过一个多层次复制可以节省相当于值的选件类,启用移动构造和移动分配有效的。 考虑以下伪代码:
#include <memory>
#include <stdexcept>
using namespace std;
// ...
class my_class {
unique_ptr<BigHugeData> data;
public:
my_class( my_class&& other ) // move construction
: data( move( other.data ) ) { }
my_class& operator=( my_class&& other ) // move assignment
{ data = move( other.data ); return *this; }
// ...
void method() { // check (if appropriate)
if( !data )
throw std::runtime_error("RUNTIME ERROR: Insufficient resources!");
}
};
如果启用复制构造/分配,还可实现移动构造/分配,则超过一个多层次复制可以节省。
这些 非值 类型是移动,例如,当无法克隆资源时,因此,只有所有权转移。 示例:unique_ptr。
节
内容