【无标题】

文章探讨了C++中的数组初始化方法,包括声明时初始化、memset函数和for循环赋值。同时,解释了数组作为参数传递时的行为以及如何获取数组大小。此外,还介绍了左值和右值的概念,以及C++11中对右值引用的细化,包括纯右值和将亡值,并通过例子展示了移动语义的应用。
摘要由CSDN通过智能技术生成

C++学习问题记录

1、数组

C语言中数组的大小必须是在编译时就能确定的,它有以下几种初始化方法:

// 声明时,使用 {0} 初始化。例如:
int a[10] = {0}; // 将数组a的所有元素初始化为0

// 使用 memset 函数初始化。这个函数可以将一段内存区域的内容全部设置为指定的值,通常用于字符数组或结构体的初始化。例如:
char s[20];
memset(s, 'a', 20); // 将数组s的所有元素初始化为字符'a'

// 用 for 循环赋值。这个方法可以对数组的每个元素进行自定义的赋值操作,比较灵活。例如:
int b[10];
for (int i = 0; i < 10; i++) {
  b[i] = i * i; // 将数组b的每个元素初始化为其下标的平方
}

现有一个数组arr,当你直接使用arr时,它表示该数组第一个元素的指针;但
当你使用sizeof(arr)时,它表示整个数组。

数组的传参,数组通过函数传参后会退化为指针,因此传参时必须传递数组大小:

void print_array(int *arr, int n) {
  for (int i = 0; i < n; i++) {
    printf("%d ", *(arr + i));
  }
  printf("\n");
}

int main() {
  int arr[] = {1, 2, 3, 4, 5};
  print_array(arr, 5); // arr是一个指针,指向数组第一个元素
}

求一个数组的大小,是很麻烦的,必须通过以下方法:

int len_arr = sizeof(arr) / sizeof(int);

2、左值右值

左值和右值的概念是从C语言继承过来的,原始的意思是根据赋值符号而定,在赋值符号左边的称为左值,在右边称为右值。左值一般是指可以被取地址并且可以修改的变量,而右值则是指不能被取地址并且不能修改的变量。

int a = 10; // a是一个左值,10是一个右值
int b = a + 5; // b是一个左值,a + 5是一个右值
int &c = b; // c是一个左值引用,绑定到b
int &&d = a + 5; // d是一个右值引用,绑定到a + 5

在C++11中,为了支持移动语义和完美转发等特性,右值又被细分为纯右值(prvalue)和将亡值(xvalue)。纯右值表示临时的、不具名的、不可修改的对象,如字面量或函数返回非引用类型的对象。将亡值表示即将被销毁或者转移所有权的对象,如函数返回非常量引用类型或者std::move返回的对象。例如:

std::string foo() {
  return "hello";
}

std::string& bar() {
  static std::string s = "world";
  return s;
}

std::string s1 = foo(); // foo()返回一个纯右值
std::string s2 = bar(); // bar()返回一个将亡值
std::string&& s3 = std::move(s1); // std::move(s1)返回一个将亡值

通过一个案例说明std::move

#include <iostream>
#include <cstring>
using namespace std;

class Person {
public:
    char* name; // 指针成员
    Person(const char* n) { // 构造函数
        name = new char[strlen(n) + 1];
        strcpy(name, n);
    }
    Person(const Person& p) { // 拷贝构造函数
        cout << "Copy constructor called" << endl;
        name = new char[strlen(p.name) + 1];
        strcpy(name, p.name);
    }
    Person(Person&& p) { // 移动构造函数
        cout << "Move constructor called" << endl;
        name = p.name; // 直接将p的资源转移到自身
        p.name = nullptr; // 将p置为空
    }
    ~Person() { // 析构函数
        delete[] name;
    }
};

int main() {
    Person p1("Alice"); // 调用构造函数
    cout << "p1's name: " << p1.name << endl;
    
    Person p2(p1); // 调用拷贝构造函数,深拷贝p1的资源
    cout << "p2's name: " << p2.name << endl;
    
    Person p3(std::move(p1)); // 调用移动构造函数,移动p1的资源
    cout << "p3's name: " << p3.name << endl;
    
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值