网上购物网站建设公司,软件制作权,wordpress文章自动分类,网站建设为什么需要备案强制生成 不生成
在C中#xff0c;可以通过一些方式来控制编译器是否生成某些特殊成员函数#xff08;如默认构造函数、拷贝构造函数、拷贝赋值运算符、析构函数等#xff09;。 默认生成#xff1a;如果你没有显式地定义这些特殊成员函数#xff0c;编译器会自动生成它们…强制生成 不生成
在C中可以通过一些方式来控制编译器是否生成某些特殊成员函数如默认构造函数、拷贝构造函数、拷贝赋值运算符、析构函数等。 默认生成如果你没有显式地定义这些特殊成员函数编译器会自动生成它们。这被称为默认生成。默认生成的成员函数会根据类的特性进行生成例如默认构造函数会生成一个无参构造函数拷贝构造函数会生成一个按值拷贝的构造函数。 强制生成如果你显式地声明了某个特殊成员函数但是不提供其定义编译器将不会生成该函数的默认实现。这被称为强制生成。通过强制生成你可以禁止某些特殊成员函数的自动生成从而实现特定的语义或行为。 不生成如果你显式地删除了某个特殊成员函数编译器将不会生成该函数的默认实现。这被称为不生成。通过不生成你可以禁止某些特殊成员函数的使用从而防止不希望的行为或错误。
下面是一些示例代码展示了如何强制生成或不生成特殊成员函数
class MyClass {
public:// 强制生成默认构造函数MyClass() default;// 强制生成拷贝构造函数MyClass(const MyClass other) default;// 不生成拷贝赋值运算符MyClass operator(const MyClass other) delete;// 强制生成析构函数~MyClass() default;
};在上面的示例中我们通过使用default关键字来强制生成默认构造函数、拷贝构造函数和析构函数。同时我们通过使用delete关键字来不生成拷贝赋值运算符。
需要注意的是强制生成或不生成特殊成员函数是一种高级用法需要谨慎使用。你应该根据具体的需求和设计来决定是否需要强制生成或不生成某些特殊成员函数。
// 以下代码在vs2013中不能体现在vs2019下才能演示体现上面的特性。
class Person
{
public:Person(const char* name , int age 0):_name(name), _age(age){}Person(const Person p):_name(p._name), _age(p._age){}Person operator(const Person p){if (this ! p){_name p._name;_age p._age;}return *this;}// 强制生成移动构造和移动赋值Person(Person p) default;Person operator(Person p) default;//不想生产让Person对象拷贝Person(const Person p) delete;~Person(){cout ~Person() endl;}private:bit::string _name; // 自定义类型int _age 1; // 内置类型};int main(){Person s1(张三, 18);Person s2 s1;Person s3 std::move(s1);cout endl endl;Person s4;s4 std::move(s2);return 0;}final || override
在C中final和override是两个关键字用于对类的成员函数进行修饰和控制。
final关键字final用于修饰类、虚函数和成员函数表示它们不能被继承、重写或覆盖。当一个类被声明为final时其他类就不能从该类派生。当一个虚函数被声明为final时它不能在派生类中被重写或覆盖。当一个非虚函数被声明为final时它不能在派生类中被重新定义。
class Base final {// ...
};class Derived : public Base { // 错误Base类被声明为final不能被继承// ...
};class Base {
public:virtual void foo() final {// ...}
};class Derived : public Base {
public:void foo() override { // 错误foo函数被声明为final不能被重写// ...}
};override关键字override用于修饰派生类中的虚函数表示该函数是对基类中的虚函数的重写。使用override可以提高代码的可读性和安全性确保派生类中的函数与基类中的虚函数具有相同的签名。
class Base {
public:virtual void foo() {// ...}
};class Derived : public Base {
public:void foo() override { // 明确标记为重写虚函数// ...}
};如果在派生类中使用了override关键字修饰一个函数但该函数并不是基类中的虚函数编译器将会报错。
总之final和override是C11引入的关键字用于对类的成员函数进行修饰和控制。final表示类或函数不能被继承、重写或覆盖而override表示派生类中的函数是对基类中虚函数的重写。
要求delete关键字实现一个类只能在堆上创建对象
当构造函数被声明为私有时它只能在类的内部被访问。这意味着在类的外部无法直接调用构造函数来创建对象。因此将构造函数设为私有可以阻止类在栈上创建对象的方式。
在C中当你在栈上声明一个对象时编译器会在编译时自动调用类的构造函数来创建对象。但是如果构造函数是私有的编译器将无法调用该构造函数从而阻止了在栈上创建对象的方式。
以下是一个示例代码展示了私有构造函数如何阻止类在栈上创建对象的方式
class MyClass {
private:MyClass() {} // 私有的构造函数public:void doSomething() {// 对象的成员函数}
};int main() {MyClass obj; // 编译错误无法调用私有构造函数return 0;
}在上面的示例中我们将构造函数声明为私有的然后在main()函数中尝试在栈上创建一个MyClass对象。由于构造函数是私有的编译器将无法调用该构造函数从而导致编译错误。
需要注意的是尽管无法在栈上直接创建对象但仍然可以通过其他方式如静态成员函数或友元函数在堆上创建对象。
class HeapOnly
{
public:~HeapOnly() delete;
};
int main()
{//HeapOnly hp1;//static HeapOnly hp2; //自定义类型会调用析构HeapOnly* ptr new HeapOnly; //指针不会调用析构return 0;
}下面例子此时会有资源泄露
class HeapOnly
{
public:HeapOnly(){_str new char[10];}~HeapOnly() delete;
private:char* _str;
};
int main()
{//HeapOnly hp1;//static HeapOnly hp2; //自定义类型会调用析构HeapOnly* ptr new HeapOnly; //指针不会调用析构//delete ptr; //无析构 不能deletereturn 0;
}自写destroy解决
// 要求delete关键字实现一个类只能在堆上创建对象
class HeapOnly
{
public:HeapOnly(){_str new char[10];}~HeapOnly() delete;void Destroy(){delete[] _str; operator delete(this);}
private:char* _str;
};
int main()
{//HeapOnly hp1;//static HeapOnly hp2; //自定义类型会调用析构HeapOnly* ptr new HeapOnly; //指针不会调用析构//delete ptr; //无析构 不能deleteptr-Destroy();return 0;
}可变参数模板 //可变参数的函数模板
template class ...Args
void ShowList(Args... args)
{cout sizeof...(args) endl; //计算几个参数
}
int main()
{string str(hello);ShowList(1);ShowList();ShowList(1, 2);ShowList(1, A, str);return 0;
}递归看参数
//可变参数的函数模板
void ShowList()
{cout endl;
}template class T, class ...Args
void ShowList(const T val, Args... args)
{cout val ;ShowList(args...);//cout sizeof...(args) endl;
}
int main()
{string str(hello);ShowList(1);ShowList();ShowList(1, 2);ShowList(1, A, str);return 0;
}结果
11 2
1 A hello列表初始化获取
templateclass T
int PrintArg(const T x)
{cout x ;return 0;
}
template class ...Args
void ShowList(Args... args)
{int a[] { PrintArg(args)... };cout endl;
}
int main()
{string str(hello);ShowList(1);ShowList();ShowList(1, 2);ShowList(1, A, str);return 0;
}emplace
emplace_back()是C标准库容器如vector、list和deque提供的一个成员函数用于在容器的末尾直接构造对象而不需要显式地调用构造函数。
emplace_back()的优势主要体现在以下几个方面 减少对象的拷贝或移动使用emplace_back()可以直接在容器的末尾构造对象而不需要先创建一个临时对象然后再将其拷贝或移动到容器中。这样可以减少不必要的对象拷贝或移动操作提高代码效率。 简化代码相比于显式地调用构造函数和push_back()函数使用emplace_back()可以更简洁地创建对象并将其添加到容器中。你只需要传递构造函数所需的参数而不需要创建临时对象或手动调用构造函数。 支持完美转发emplace_back()函数支持完美转发可以将参数直接传递给构造函数无需手动进行类型转换。这意味着你可以使用不同类型的参数来构造对象而不需要为每个类型编写重载的构造函数。
以下是一个使用emplace_back()的示例代码
#include vectorclass MyClass {
public:MyClass(int x, int y) {// 构造函数的实现}
};int main() {std::vectorMyClass myVector;myVector.emplace_back(10, 20); // 在容器的末尾构造对象return 0;
}在上面的示例中我们使用emplace_back()函数在myVector容器的末尾直接构造了一个MyClass对象而不需要先创建一个临时对象。
总而言之emplace_back()函数可以提高代码的效率和可读性减少对象的拷贝或移动并支持完美转发使代码更加简洁和灵活。
emplace支持参数包
定位new
内存池 显示的调用构造函数
lambda 简单的lambda函数
int mian()
{//两个数相加的lambdaauto add1 [](int a, int b)-int{return a b; };cout add1(1, 2) endl;//省略返回值auto add2 [](int a, int b){return a b; };cout add2(1, 2) endl;//交换变量的lambdaint x 0, y 1;auto swap1 [](int x1, int x2)-void {int tmp x1; x1 x2; x2 tmp; };swap1(x, y);cout x : y endl;auto swap2 [](int x1, int x2){int tmp x1; x1 x2; x2 tmp; };swap2(x, y);cout x : y endl;//不传参数交换xy lambda --捕捉列表 (默认捕捉过来的变量不能修改 加mutable)//auto swap3 [x, y]()mutable //无修改作用auto swap3 [x, y]() //传引用捕捉{int tmp x;x y;y tmp;};swap3();cout x : y endl;return 0;
}lambda作为sort的参数之前用反函数对象或者类型实现 sort(v.begin(), v.end(), [](const Goods g1, const Goods g2) {return g1._name g2._name; });