C++ 类与对象——超详细入门指南(上篇)

C++ 类与对象——详细入门指南

1. 类的定义

在C++中,类是面向对象编程的基础概念之一。类通过将数据和行为封装在一起,模拟现实世界中的实体。通过类,我们可以定义对象的属性(成员变量)和行为(成员函数)。

1.1 类定义的基本格式

类的定义使用 class 关键字,后面跟上类的名称。在C++中,类体需要用大括号 {} 包裹,并在类定义结束时加上分号 ;。类中的内容称为类的成员,包括:

  • 成员变量:即类的属性,存储类的状态。
  • 成员函数:即类的方法,定义类的行为。
示例代码
#include <iostream>
using namespace std;class Stack {
public:// 成员函数:初始化栈void Init(int n = 4) {array = (int*)malloc(sizeof(int) * n);if (nullptr == array) {perror("malloc申请空间失败");return;}capacity = n;top = 0;}// 成员函数:将元素推入栈void Push(int x) {// 如果栈满,进行扩容array[top++] = x;}// 成员函数:获取栈顶元素int Top() {assert(top > 0);return array[top - 1];}// 成员函数:销毁栈void Destroy() {free(array);array = nullptr;top = capacity = 0;}private:// 成员变量:栈的实现细节int* array;size_t capacity;size_t top;
};int main() {Stack st;st.Init();st.Push(1);st.Push(2);cout << st.Top() << endl;st.Destroy();return 0;
}
解释
  • class:定义类的关键字。
  • Stack:类的名称。
  • 成员函数:例如 InitPushTopDestroy,它们定义了类的行为。
  • 成员变量:例如 arraycapacitytop,这些变量存储类的状态或属性。
  • public/private:访问限定符,决定了类的成员是如何被访问的。public 成员可以在类外访问,private 成员则只能在类内部使用。

1.2 访问限定符

访问限定符是C++实现封装的方式之一,它决定了类的成员能否被类外部的用户访问。

  • public:修饰的成员可以在类外部直接访问。
  • private:修饰的成员只能在类内部访问,类外不能直接访问。
  • protected:类似于 private,但在继承中,子类可以访问 protected 成员。之后会详细讲解
示例代码
class Date {
public:// 公有成员函数void Init(int year, int month, int day) {_year = year;_month = month;_day = day;}private:// 私有成员变量int _year;int _month;int _day;
};int main() {Date d;d.Init(2024, 3, 31);return 0;
}
解释
  • public:声明的 Init 函数是公共的,可以在类外部使用。
  • private_year_month_day 是私有成员,不能在类外部直接访问,只有类的成员函数能访问这些变量。

1.3 类域

类的作用域决定了类成员的可访问性。在类外定义成员函数时,需要通过作用域解析符 :: 指明成员属于哪个类。例如,如果在类外定义成员函数,需要使用类名和作用域解析符。

示例代码
#include <iostream>
using namespace std;class Stack {
public:void Init(int n = 4);
private:int* array;size_t capacity;size_t top;
};// 使用作用域解析符在类外定义成员函数
void Stack::Init(int n) {array = (int*)malloc(sizeof(int) * n);if (nullptr == array) {perror("malloc申请空间失败");return;}capacity = n;top = 0;
}int main() {Stack st;st.Init();return 0;
}
解释
  • Stack::Init:: 作用域解析符表示 Init 函数属于 Stack 类。通过作用域解析符,编译器可以知道该函数属于哪个类,并可以在类的作用域中查找成员变量 arraycapacitytop

1.4 成员命名规范

在C++中,通常会为类的成员变量使用特定的命名约定,以避免与函数参数或局部变量混淆。这些命名约定可以提高代码的可读性和维护性。

常见的命名约定:
  1. 使用下划线 _:在成员变量的名称前加一个下划线,以区分成员变量和其他变量。
  2. 使用 m_ 前缀:成员变量以 m_ 开头,表示 “member”(成员变量)。
  3. 驼峰命名法:使用驼峰命名法,例如 myVariable,使得代码更易读。
示例:
class Date {
private:int _year;       // 使用下划线前缀int m_month;     // 使用 m_ 前缀int dayOfMonth;  // 使用驼峰命名法
public:void SetDate(int year, int month, int day) {_year = year;m_month = month;dayOfMonth = day;}
};
拓展:

这种命名约定并不是C++语言的强制要求,而是遵循公司或团队的编码风格指南。使用这些命名约定可以避免命名冲突,并让代码的意图更加明确。例如,在 SetDate 函数中,使用 _yearyear 可以轻松区分成员变量和函数参数,减少混淆。

1.5 class与struct的默认访问权限

在C++中,classstruct 的区别主要在于默认的访问权限:

  • class 中,未标明的成员变量和成员函数默认是 private
  • struct 中,未标明的成员变量和成员函数默认是 public
示例:
struct ExampleStruct {int a; // 默认 public
};class ExampleClass {int b; // 默认 private
};

2. 类的实例化

2.1 实例化概念

实例化是指在物理内存中创建对象的过程。类是对象的抽象描述,它提供了对象的结构和行为,但是类本身并不占用物理空间,只有当类被实例化时,才会在内存中分配空间。

示例代码
#include <iostream>
using namespace std;class Date {
public:void Init(int year, int month, int day) {_year = year;_month = month;_day = day;}void Print() {cout << _year << "/" << _month << "/" << _day << endl;}private:int _year;int _month;int _day;
};int main() {Date d1;d1.Init(2024, 3, 31);d1.Print();Date d2;d2.Init(2024, 7, 5);d2.Print();return 0;
}
解释
  • Date d1:实例化一个 Date 对象 d1
  • Init:调用 Init 函数初始化 d1 对象的成员变量 _year_month_day
  • Print:输出对象的日期信息。

2.2 对象的大小

当类被实例化为对象时,对象的大小取决于类的成员变量成员变量需要分配空间,但成员函数不会在对象中存储。成员函数是存储在单独的代码段中的一段指令。

示例代码
#include <iostream>
using namespace std;class A {
private:char _ch;  // 1 字节int _i;    // 4 字节
};int main() {A a;cout << sizeof(a) << endl;  // 输出对象的大小return 0;
}
解释
  • 该类的成员变量 _ch_i 总共占用 5 字节,但由于内存对齐,实际对象的大小可能是 8 字节。内存对齐规则保证了访问效率(见下文解释)。

2.3 对象的存储

在C++中,当类被实例化为对象时,只有成员变量会被存储在对象中,而成员函数不会。成员函数是存储在代码段中的一段指令,所有对象共享同一份函数指令。因此,无论类有多少个对象,成员函数只会存在一份。

示例:
class Date {
public:void Init(int year, int month, int day);
private:int _year;int _month;int _day;
};

3. this 指针

3.1 什么是 this 指针

this 是C++中的一个隐式指针,存在于每一个非静态成员函数中。this 指针指向调用该成员函数的当前对象。在类的成员函数中,this 指针可以用来访问类的成员变量和成员函数。

  • 当我们在成员函数中使用类的成员变量时,本质上是通过 this 指针访问该成员变量。
  • this 指针是隐含的,C++自动将它传递给所有非静态成员函数。
this 指针的内部机制

在C++中,当类的成员函数被调用时,this 指针会被自动传递给该函数。this 指针的类型是 const Type* const,它是一个只读指针,指向当前对象。你不能修改 this 指针的值,但可以通过 this 访问对象的成员。

3.2 示例代码

#include<iostream>
using namespace std;class Date {
public:void Init(int year, int month, int day) {this->_year = year;  // 通过 this 指针访问成员变量this->_month = month;this->_day = day;}void Print() {cout << _year << "/" << _month << "/" << _day << endl;}private:int _year;int _month;int _day;
};int main() {Date d1;d1.Init(2024, 3, 31);d1.Print();return 0;
}
解释
  • this:在 Init 函数中,this->_year = year 表示将传入的参数 year 赋值给当前对象的 _year 成员变量。this 指针指向当前调用 Init 函数的对象(即 d1)。
拓展解释:this 指针在什么时候使用?

在通常的情况下,编写代码时我们不需要显式使用 this 指针,因为C++会自动处理类的成员和参数之间的冲突。但是在某些情况下,例如当函数的参数名称和成员变量名称相同时,使用 this 指针可以明确地表示成员变量。

void Init(int year, int month, int day) {this->_year = year;  // 通过 this 指针区分成员变量和函数参数this->_month = month;this->_day = day;
}

在上面的代码中,如果不使用 this,编译器会把 year 解释为函数参数,而不是成员变量 _year

好的,我会在 this 指针部分补充所有的测试内容,并在该部分加入关于 命名 的内容,确保详细且连贯。以下是需要补充的内容:


3.3 this指针的测试题

测试题 1:this 指针的基本行为

#include<iostream>
using namespace std;class A {
public:void Print() {cout << "A::Print()" << endl;}
private:int _a;
};int main() {A* p = nullptr;p->Print();  // 能否正常运行?return 0;
}
问题描述:

我们定义了一个 A 类,包含一个成员函数 Print(),它只是输出一条字符串。我们通过空指针 p 调用 Print() 函数,询问这段代码能否正常运行。

解析:
  1. main() 函数中,A* p = nullptr; 创建了一个指向 A 类的空指针 p
  2. 随后我们通过空指针 p->Print() 来调用成员函数 Print(),这里的 this 指针其实是空指针。

为什么不会报错?

  • 当我们调用 p->Print() 时,this 指针实际上等于 nullptr,但由于 Print() 函数没有访问任何成员变量,因此C++允许这个调用。
  • this 指针是隐含的,虽然在函数内部会传递 this,但是如果成员函数不访问任何成员变量,C++不需要解引用这个空指针,因此不会出现空指针访问的错误。
  • Print() 函数只是输出了一段固定的文本,不涉及对象的状态或成员变量,因此即使 this 是空指针,也不会导致问题。
正确答案:C. 正常运行

测试题 2:this 指针与成员变量的访问

#include<iostream>
using namespace std;class A {
public:void Print() {cout << "A::Print()" << endl;cout << _a << endl;}
private:int _a;
};int main() {A* p = nullptr;p->Print();  // 能否正常运行?return 0;
}
问题描述:

这段代码和前一个问题类似,但在 Print() 函数中多了一个成员变量 _a 的访问。通过空指针 p 调用 Print(),是否会出现空指针访问的问题?

解析:
  1. main() 中,和之前一样,A* p = nullptr; 创建了一个指向 A 类的空指针 p
  2. 当调用 p->Print() 时,this 指针仍然是 nullptr

为什么会崩溃?

  • Print() 函数中,除了输出 A::Print() 以外,代码还试图访问类的成员变量 _a
  • this 指针为 nullptr 时,访问 this->_a 等同于尝试通过空指针访问成员变量。这是一种未定义行为,在大多数系统中会导致程序崩溃。
  • 成员变量 _a 存储在对象的内存空间中,而通过空指针访问成员变量时,由于没有实际的对象空间可用,因此程序在运行时会发生崩溃。
正确答案:B. 运行时崩溃

详细解释:为什么不是空指针访问

在这两个测试题中,关键点在于是否访问了成员变量

  1. 测试题 1 中,Print() 函数没有访问成员变量,所以即使 this 是空指针,C++也不会触发空指针访问错误。这是因为成员函数本质上只是一个在内存中的函数指针,调用它并不一定需要访问实际对象的内存。

  2. 测试题 2 中,Print() 函数试图访问成员变量 _a。由于成员变量存储在对象的内存空间中,而空指针 this 并没有指向有效的内存区域,所以在运行时会试图通过空指针访问内存,导致程序崩溃。这是典型的空指针访问错误。

总结来说,空指针调用成员函数本身并不会报错,只要该成员函数不涉及访问成员变量或其他依赖对象内存的操作。然而,一旦成员函数试图通过 this 指针访问成员变量,程序就可能会崩溃,因为 thisnullptr,没有有效的内存空间可供访问。


测试题 3:this 指针的存储位置

选择题:this 指针存在于内存的哪个区域?

  • A. 栈
  • B. 堆
  • C. 静态区
  • D. 常量区
  • E. 对象里

正确答案:A. 栈

解释
this 指针作为成员函数的一个隐含参数,存储在栈中。每当一个成员函数被调用时,this 指针会作为函数参数被压入栈中。


4. C++和C语言实现Stack的对比

通过C和C++语言实现 Stack 栈的对比,展现了C++相较于C语言在封装和安全性方面的优势。

4.1 C语言实现Stack

在C语言中,实现 Stack 需要使用 struct 来定义栈的数据结构,并且所有的栈操作(如初始化、压栈、弹栈等)都通过独立的函数实现。由于C语言不支持面向对象编程,数据和操作必须分开处理,所有栈操作的函数需要手动传递 Stack 结构体的指针作为参数。

C语言实现Stack的代码示例
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
#include<assert.h>typedef int STDataType;
typedef struct Stack {STDataType* array;int top;int capacity;
} Stack;void Init(Stack* s) {s->array = (STDataType*)malloc(4 * sizeof(STDataType));s->capacity = 4;s->top = 0;
}void Destroy(Stack* s) {free(s->array);s->array = NULL;s->top = 0;s->capacity = 0;
}void Push(Stack* s, STDataType x) {if (s->top == s->capacity) {s->capacity *= 2;s->array = (STDataType*)realloc(s->array, s->capacity * sizeof(STDataType));}s->array[s->top++] = x;
}STDataType Top(Stack* s) {assert(s->top > 0);return s->array[s->top - 1];
}void Pop(Stack* s) {assert(s->top > 0);--s->top;
}bool Empty(Stack* s) {return s->top == 0;
}int main() {Stack s;Init(&s);Push(&s, 1);Push(&s, 2);printf("栈顶元素: %d\n", Top(&s));Pop(&s);printf("栈顶元素: %d\n", Top(&s));Destroy(&s);return 0;
}
C语言实现Stack的详细解释
  • 结构体Stack:这是一个结构体,包含了三个成员:

    • array:一个指向栈的动态数组的指针,用来存储栈中的元素。
    • top:指向栈顶元素的指针,它代表当前栈中元素的个数。
    • capacity:栈的容量,表示栈中最多可以容纳的元素个数。
  • 函数Init:用于初始化栈的大小,并为数组分配内存。C语言中没有构造函数,因此必须通过函数显式初始化结构体。

  • 函数Push:将元素压入栈中,如果栈满则进行扩容操作,使用 realloc 函数为栈分配更大的内存。

  • 函数Top:返回栈顶元素,调用时需要确保栈不为空。

  • 函数Pop:将栈顶元素弹出,减少 top 的值。

  • 内存管理:通过 mallocrealloc 动态分配内存,使用 free 释放内存。


4.2 C++语言实现Stack

C++通过类的封装,可以将数据和操作放在一起。栈的实现不仅更为简洁,而且通过封装性提高了代码的安全性和可维护性。相比C语言,C++不需要手动传递 Stack 指针,而是通过类的成员函数自动操作栈。

C++实现Stack的代码示例
#include<iostream>
using namespace std;class Stack {
public:Stack(int n = 4) {_array = (int*)malloc(sizeof(int) * n);_capacity = n;_top = 0;}~Stack() {free(_array);_array = nullptr;}void Push(int x) {if (_top == _capacity) {_capacity *= 2;_array = (int*)realloc(_array, _capacity * sizeof(int));}_array[_top++] = x;}int Top() {assert(_top > 0);return _array[_top - 1];}void Pop() {assert(_top > 0);--_top;}bool Empty() {return _top == 0;}private:int* _array;size_t _capacity;size_t _top;
};int main() {Stack s;s.Push(1);s.Push(2);cout << "栈顶元素: " << s.Top() << endl;s.Pop();cout << "栈顶元素: " << s.Top() << endl;return 0;
}
C++实现Stack的详细解释
  • 构造函数和析构函数

    • 构造函数 Stack(int n = 4):用于初始化栈,分配内存并设置栈的容量。这里的 n 是栈的初始大小,默认值为4。构造函数在对象创建时自动调用,确保对象处于有效的状态。
    • 析构函数 ~Stack():当栈对象被销毁时,自动释放动态分配的内存。这是C++相比C语言的一个显著优势,因为不需要手动调用 Destroy 函数来释放资源。
  • 成员函数Push:与C语言中的 Push 函数类似,用于将元素压入栈中。栈满时会自动扩容,但通过成员函数的封装,这一操作对类外的用户是透明的,用户只需要调用 Push 方法即可。

  • 成员函数Top:返回栈顶元素,和C语言一样,操作之前会检查栈是否为空,保证操作的安全性。

  • 封装性:相比C语言,C++通过类的 private 成员变量 _array_capacity_top,将栈的实现细节封装起来,防止用户直接操作这些数据。所有的操作都通过 public 成员函数完成,保证了数据的安全性。

拓展解释:构造函数和析构函数(在之后会详细解释
  • 构造函数:它是类中的特殊函数,当类的对象被创建时,构造函数会被自动调用,用于初始化对象。在 Stack 类中,构造函数初始化栈的容量,并为数组分配内存。

  • 析构函数:它也是类中的特殊函数,当对象生命周期结束(如对象作用域结束时)时,析构函数会自动调用,用于释放对象所占用的资源。在 Stack 类中,析构函数用于释放 malloc 分配的内存,避免内存泄漏。


4.3 C++和C语言实现Stack的对比总结

通过对C和C++实现 Stack 的对比,可以得出以下几点总结:

  • 封装性:C++通过类的封装将数据和操作整合在一起,类的用户不需要关心栈的实现细节,而C语言的实现则需要用户手动调用函数并管理结构体的状态。

  • 内存管理:C语言中,内存管理是手动的,开发者必须显式调用 free 函数释放内存。而在C++中,析构函数自动负责资源的释放,避免了忘记释放内存导致的内存泄漏问题。

  • 安全性:C++中的类通过 private 关键字保护类的内部数据,防止外部代码随意修改类的成员变量,增强了数据的安全性。而C语言没有这种封装机制,所有数据都可以通过结构体直接访问,容易导致意外的修改和错误。


5. 内存对齐

内存对齐是计算机系统中用于优化数据访问的机制。在C++中,类的成员变量在内存中的存放位置要遵循特定的对齐规则,以提高CPU的访问效率。

这部分内容在C语言结构体详细介绍过,详情请见

5.1 内存对齐规则

内存对齐规则规定:

  1. 第一个成员存储在偏移量为0的地址处。

  2. 其他成员必须存储在某个对齐数的整数倍的地址处。

  3. 对齐数取决于编译器的设置和变量的类型,通常为4字节或8字节。

5.2 示例代码

#include<iostream>
using namespace std;class A {
private:char _ch;  // 1 字节int _i;    // 4 字节
};int main() {A a;cout << "对象 A 的大小: " << sizeof(a) << " 字节" << endl;  // 输出对象大小return 0;
}
解释

尽管 A 类中的 _ch_i 变量加起来只有 5 字节,但由于内存对齐规则,类的实际大小为 8 字节。这是因为 int 变量 _i 要求4字节对齐,而 char 只占1字节,因此在 char 后面会插入3个字节的填充空间,以便 int 对齐到4字节边界。

拓展解释:为什么需要内存对齐?
  • 内存对齐的意义:内存对齐的目的是为了优化CPU的读取速度。在现代计算机架构中,处理器一次性读取的内存块大小通常为4字节或8字节。如果数据存储在不对齐的地址上,处理器需要执行更多的操作来读取数据,从而影响性能。因此,通过对齐存储,处理器可以更快速地读取和写入数据。

  • 内存对齐和空间浪费:虽然内存对齐提高了数据访问的效率,但也可能会造成空间浪费。例如,在上例中,char 类型只需要1字节,但为了对齐 int,额外浪费了3个字节的填充空间。这种权衡在性能优化和内存空间利用之间找到了平衡。


5.3 内存对齐的影响

内存对齐会影响类的实际大小。例如,以下代码展示了不同对齐方式下对象的大小变化:

#include<iostream>
#pragma pack(1)  // 设置内存对齐为1字节
using namespace std;class B {
public:char _ch;  // 1字节int _i;    // 4字节
};int main() {B b;cout << "对象 B 的大小: " << sizeof(b) << " 字节" << endl;  // 输出对象 B 的大小为 5 字节return 0;
}
#pragma pack()  // 恢复默认对齐
解释

通过使用 #pragma pack(1) 指令,我们将类 B 的内存对齐设置为 1 字节对齐。这样,char 类型占用 1 字节,int 类型占用 4 字节,总共5字节,没有插入额外的填充字节。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/1556130.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

工具 | 红队大佬亲测5款推荐的Burpsuite插件

*免责声明&#xff1a;* *本文章仅用于信息安全技术分享&#xff0c;请勿利用文章内的相关技术从事非法测试&#xff0c;由于传播、利用此文所提供的信息或者工具而造成的任何直接或者间接的后果及损失&#xff0c;均由使用者本人负责&#xff0c;所产生的一切不良后果与文章作…

【LeetCode-热题100-128题】官方题解好像有误

最长连续序列 题目链接&#xff1a;https://leetcode.cn/problems/longest-consecutive-sequence/?envTypestudy-plan-v2&envIdtop-100-liked 给定一个未排序的整数数组 nums &#xff0c;找出数字连续的最长序列&#xff08;不要求序列元素在原数组中连续&#xff09;的…

LLM大模型学习精要系列(一):掌握基础,开启大模型之旅

1.前言 1.1 基础模型研究 2023 年&#xff0c;随着 LLM 技术的发展&#xff0c;中国模型研究机构的开源模型迎来了爆发式的增长&#xff1a; 2023 年 3 月&#xff0c;智谱 AI 首先在魔搭社区发布了 ChatGLM-6B 系列&#xff0c;ChatGLM-6B 是一个开源的、支持中英双语问答的…

如何只修改obsidian图片链接为markdown

如何只修改obsidian图片链接为markdown 前言插件配置 使用注意 前言 适合有一定了解obsidian用法和插件市场&#xff0c;还有相对路径的人 插件 在obsidian插件市场搜索—开梯子 配置 首先使用ctrlp打开命令面板&#xff0c;也可以在左侧通过图标打开命令面板&#xff0c…

车载电子电气架构--- 车载诊断DTC全覆盖分类

我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 屏蔽力是信息过载时代一个人的特殊竞争力,任何消耗你的人和事,多看一眼都是你的不对。非必要不费力证明自己,无利益不试图说服别人,是精神上的节…

智能制造的人机料法环的内涵

在生产和管理领域,有个很重要的概念叫 “人、机、料、法、环”。 “人” 就是参与其中的人员,他们的技能、态度、责任心等对事情的结果影响很大; “机” 指的是机器设备和工具等,就像干活要用的家伙事儿,好不好用、正不正常直接关系到工作的效率和质量; “料” 呢,就…

MathType软件7.9最新版本下载超实用指南

嗨&#xff0c;各位学霸、研究僧还有教育界的大佬们&#xff01;&#x1f44b; 今天我要给你们安利的不是一道数学题&#xff0c;也不是一本教科书&#xff0c;而是一款让你分分钟爱上数学的神器——MathType软件&#xff01;&#x1f389; #### &#x1f4da; **MathType是什…

DataX+Crontab实现多任务顺序定时同步

DataX+Crontab实现多任务顺序定时同步 前言 DataX 是一款支持在异构数据源之间离线同步数据的工具, DataX 通过输入一些命令执行 json 配置文件,这样使用起来并不是很方便, DataX 也不支持定时任务调度,它仅支持一次性同步任务。所以 DataX 的这些特点造成了它无法完成一些…

S7-200 SMART Modbus RTU常见问题

1.S7-200 SMART 是否支持 Modbus ASCII 通信模式&#xff1f; STEP 7-Micro/WIN SMART 软件未提供Modbus ASCII 通信模式指令库。S7-200 SMART CPU若用于Modbus ASCII 通信时&#xff0c;则需要用户使用自由口通信模式进行编程。 2.S7-200 SMART CPU 集成的RS485 端口&#xf…

YOLOv10改进,YOLOv10添加CA注意力机制,二次创新C2f结构,助力涨点

改进前训练结果: 二次创新C2f结构训练结果: 摘要 在本文中,提出了一种新的移动网络注意力机制,将位置信息嵌入到信道注意力中称之为“协调注意力”。与渠道关注不同通过 2D 全局池将特征张量转换为单个特征向量,坐标注意力因子将通道注意力转化为两个 1D 特征编码过程…

STAR数据集:首个用于大型卫星图像中场景图生成大规模数据集

2024-06-12&#xff0c;在遥感图像领域&#xff0c;由武汉大学等机构联合创建的STAR数据集&#xff0c;标志着场景图生成技术在大规模、高分辨率卫星图像中的新突破。 一、研究背景&#xff1a; 场景图生成(Scene Graph Generation, SGG)技术在自然图像中已取得显著进展&#…

[C语言]指针和数组

目录 1.数组的地址 2.通过指针访问数组 3.数组和指针的不同点 4.指针数组 1.数组的地址 数组的地址是什么&#xff1f; 看下面一组代码 #include <stdio.h> int main() { int arr[5] {5,4,3,2,1}; printf("&arr[0] %p\n", &arr[0]); printf(&qu…

个人网站,怎么操作才能提升个人网站的流量

运营个人网站以提升流量是一个综合性的过程&#xff0c;涉及内容优化、技术调整、用户体验提升以及外部推广等多个方面。以下是一些专业建议&#xff0c;旨在帮助个人网站运营者有效提升网站流量&#xff1a; 1.精准关键词研究与优化 -关键词研究&#xff1a;利用工具如谷歌…

【YOLO学习】YOLOv3详解

文章目录 1. 网络结构1.1 结构介绍1.2 改进 2. 训练与测试过程3. 总结 1. 网络结构 1.1 结构介绍 1. 与 YOLOv2 不同的是&#xff0c;YOLOv3 在 Darknet-19 里加入了 ResNet 残差连接&#xff0c;改进之后的模型叫 Darknet-53。在 ImageNet上 实验发现 Darknet-53 相对于 ResN…

数据结构与算法篇(树 - 常见术语)

目录 一、什么是树&#xff1f; 二、相关术语 根结点 边 叶子结点 兄弟结点 祖先结点 结点的大小 树的层 结点的深度 结点的高度 树的高度 斜树 一、什么是树&#xff1f; 树是一种类似于链表的数据结构&#xff0c;不过链表的结点是以线性方式简单地指向其后继结…

ORB-SLAM复现时遇到的问题(复现失败,切莫当做教程)

背景 本人的环境&#xff1a;使用ubuntu20.04&#xff0c;opencv4 问题 进行Build DBoW2. Go into Thirdparty/DBoW2/ and execute:时&#xff0c;运行make时出错 我安装的opencv4&#xff0c;在 OpenCV 3 和更高版本中&#xff0c;头文件的路径可能已更改。例如&#xff0…

[单master节点k8s部署]32.ceph分布式存储(三)

基于ceph rbd生成pv 在集群中认证ceph 用下面代码生成ceph的secret .创建 ceph 的 secret&#xff0c;在 k8s 的控制节点操作&#xff1a; 回到 ceph 管理节点创建 pool 池&#xff1a; [rootmaster1-admin ~]# ceph osd pool create k8stest 56 pool k8stest created [rootm…

免费音频剪辑软件大揭秘:让声音创作更轻松

在精神娱乐越发丰富的现在&#xff0c;音频内容的创作和编辑变得越来越重要。无论是专业的音乐制作人&#xff0c;还是自媒体创作者&#xff0c;都可能需要一款功能强大且易于使用的音频剪辑软件来处理音频素材。今天我们一同来探讨有什么好用的免费音频剪辑软件吧。 1.福昕音…

golang gin入门

gin是个小而精的web开发框架 官方文档 安装 go get -u github.com/gin-gonic/gin最简单的起手代码 package mainimport ("net/http""github.com/gin-gonic/gin" )func main() {r : gin.Default()r.GET("/ping", func(c *gin.Context) {c.JSON…

Java IO流全面教程

此笔记来自于B站黑马程序员 File 创建对象 public class FileTest1 {public static void main(String[] args) {// 1.创建一个 File 对象&#xff0c;指代某个具体的文件// 路径分隔符// File f1 new File("D:/resource/ab.txt");// File f1 new FIle("D:\\…