C++ 基础 一 类, 构造函数, 初始化列表 new explicit

本文深入探讨了C++中构造函数的各种类型,包括默认构造函数、带参数构造函数、拷贝构造函数及其工作原理。同时,讲解了如何使用初始化列表进行成员变量的初始化,以及new关键字在堆区创建对象的区别和析构函数的执行时机。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

c++的类

  1.编写一个.h文件     包含成员变量,方法(声明)       默认构造函数 ,析构函数

#pragma once
using namespace std;
class Person
{
public:
	Person() {
		cout << "c++的构造函数" << endl;
	};
	~Person() {
		cout << "c++的析构函数函数" << endl;
	};

	void setName(string pname);

	string getName();
	void printName();

private:
	string name;            };

  2.编写一个实现类       导入.h文件           并实现其中的方法        : :表示类作用域    

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<string>
#include"Person.h"

void Person::setName(string pname) {
	name = pname;
}

string Person::getName() {
	return name;
}
void Person::printName() {
	cout << name << endl;                }

3.测试输出结果

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include"Person.h"
using namespace std;

int main(void) {
	Person p;
	p.setName("wyc");
	cout << p.getName() << endl;   } c++的构造函数    wyc        c++的析构函数函数

2.构造函数

  1.构造函数:  默认构造函数不需要加括号执行   列如 Person p; 就会执行默认的           但是Person  p()  不会,认为是函数的声明

class Person
{
public:
	Person() {
		cout << "无参构造函数" << endl;
	};

	Person(int age) {
		cout << "有参构造函数" << endl;
	};

	Person(const Person &p) {
		m_age = p.m_age;
		cout << "拷贝参构造函数" << endl;
	};

	~Person() {
		cout << "析构函数" << endl;
	};

private:
	int m_age;                };

   2.Person(100)   称为匿名对象 ,会在这句话结束后释放这个对象,所以析构函数在这句话之后立即执行   

    3.Person p = Person(20)  而这种是随栈区而销毁        4.不能使用 拷贝构造初始化匿名对象,列如   Person( p1)

   5.Person  p2 = 100;   相当于调用有参的构造  Person  p2 = Person(100);   Person p3 = p2 相当于 Person p3 = Person(p2)

    系统默认给的:  无参构造函数  拷贝函数   析构函数    如果自己提供 普通构造,系统不再提供,默认无参,但是还是有

     如果自己提供拷贝,系统不会再提供任何默认构造函数

3.深拷贝浅拷贝

4.初始化列表

   使用下列写法,初始化多个成员变量

class Person {
public:
	Person(int a, int b, int c) :p_a(a),p_b(b),p_c(c)
	{}

	int p_a;
	int p_b;
	int p_c;            };

5.类作为成员变量

   1.调用顺序:  先调用 Phone的默认构造函数,再是Game类的, 再是自己的析构函数,再是 Phone的析构再是Game

class Person {

	Phone p;
	Game g;

};

class Phone
{
};

class Game {

};

int main() {
	Person p;
	return 0;            }

6.explicit关键字

1.如果在构造函数前加上这个,那么就可以防止隐式类型转换,列如Person p = "name" 会报错 ,相当于Person p = Person ("name");

 7.new 关键字

   1.new 关键字就相当于 第一句话

Person* p1 = (Person*)malloc(sizeof(Person));    等于
Person* p2 = new Person;

   1.之前  Person p;   这是在栈区开启的空间,函数结束会释放执行 析构函数        使用new 关键字存放在堆区,不会执行析构函数

  malloc 返回void * 使用需要强转,  不会调用默认构造,          使用new 出来的 使用 delete p     释放对象 执行析构函数

  2. new 出来的是一个指针

  3.new 开启数组         new Person [10] 执行10次构造 ,     new 数组必须有默认构造方法       delete [10] P

### 在 C++ 构造函数初始化列表中使用 `std::move` 的正确方法与注意事项 在 C++ 中,当资源管理(如 `std::unique_ptr`, `std::vector` 等)作为成员变量时,在构造函数初始化列表中合理使用 `std::move` 可以提高性能并避免不必要的拷贝操作。以下是关于此主题的具体说明。 #### 正确方法 如果希望将右值传递给构造函数并将其实例化为成员变量,则可以在初始化列表中使用 `std::move` 将临时对象的所有权转移至成员变量。例如: ```cpp class MyClass { public: std::vector<int> vec; // 接收 rvalue 并移动到成员变量 explicit MyClass(std::vector<int>&& v) : vec(std::move(v)) {} }; ``` 此处的关键在于理解何时应该调用 `std::move`。仅当参数本身已经是右值或者需要将其转换成右值以便执行移动语义时才应如此做[^1]。 #### 注意事项 1. **避免无意义的移动** 不要对左值盲目地施加 `std::move` ,因为这样会剥夺原本可重复使用的对象的生命期,并且可能带来额外开销而不是优化[^2]。 错误示范: ```cpp class BadExample { public: std::string str; BadExample(const std::string& s) : str(std::move(s)) {} // 不必要地移动了个 lvalue }; ``` 2. **区分传入参数型** 根据传入参数的不同(lvalue 或者 rvalue),决定是否需要以及如何应用 `std::move` 。对于接受常量引用 (`const T&`) 的形参来说,绝不可能对其进行修改,也就不存在所谓的“所有权转让”,所以无需也不应当对其调用 `std::move` 函数[^3]。 3. **考虑自定义分配器的影响** 如果容器采用了特殊的分配策略(比如通过模板别名指定非默认分配器),那么即使实现了移动赋值运算符也可能由于这些附加状态的存在而导致无法完全消除复制动作的发生[^4]。 4. **防止悬空指针/无效句柄等问题发生** 成功完成次有效的移动之后,源对象进入有效但未定义的状态——即它仍然合法存在但却不再持有任何实际数据。因此务必小心处理后续对该源实体的操作以防意外行为出现。 --- 综上所述,在构造函数初始化列表里恰当地运用 `std::move` 技术有助于构建高效且健壮的应用程序;但是同时也要求程序员具备足够的理论基础来判断什么时候适合采用这手段以及怎样才能做到既简洁又安全。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值