专业编程基础技术教程

网站首页 > 基础教程 正文

JS程序员学C++入门教程(上篇)

ccvgpt 2025-04-26 17:04:37 基础教程 1 ℃

1. 环境搭建与第一个程序

JavaScript (解释执行)

// 直接运行
console.log("Hello JS");

C (编译执行)

// hello.c
#include <stdio.h>
int main() {
    printf("Hello C\n");
    return 0;
}

// 编译命令: gcc hello.c -o hello
// 执行命令: ./hello

C++ (编译执行)

// hello.cpp
#include <iostream>
int main() {
    std::cout << "Hello C++" << std::endl;
    return 0;
}

// 编译命令: g++ hello.cpp -o hello
// 执行命令: ./hello

关键差异

  • JS 直接解释执行,C/C++ 需要显式编译
  • C++ 使用 std::cout 替代 C 的 printf
  • C++ 要求显式 return 0(JS 无返回值要求)

2. 变量与类型系统

JavaScript (弱类型)

let a = 10;          // 自动推导为 number
const b = "text";    // 字符串
let c = { x: 1 };    // 对象
a = "now string";    // 类型可动态改变

C (强类型/显式声明)

int a = 10;           // 必须显式声明类型
const char* b = "text"; 
int* c = &a;          // 指针类型
// a = "string";     // 编译错误:类型不匹配

C++ (强类型 + 类型推导)

int a = 10;           // 传统声明
auto b = 3.14;        // C++11 auto 推导为 double
const auto* c = "text"; // 推导为 const char*
// a = "string";      // 编译错误

JS 程序员注意

JS程序员学C++入门教程(上篇)

  1. C/C++ 中 const 是真正的常量(JS 的 const 允许修改对象内部)
  2. C++ 的 auto 不同于 JS 动态类型,编译时即确定类型

3. 作用域与生命周期

JavaScript (函数作用域)

function test() {
    if (true) {
        var x = 10;     // var 穿透块级作用域
        let y = 20;     // let 块级作用域(ES6+)
    }
    console.log(x);     // 10
    // console.log(y);  // 报错: y 未定义
}

C (块级作用域)

void test() {
    if (1) {
        int x = 10;
    }
    // printf("%d", x); // 错误: x 未定义
}

C++ (栈对象自动销毁)

void test() {
    int* ptr = new int(10); // 堆内存分配(需手动释放)
    {
        int x = 20;         // 栈变量,自动释放
    }
    delete ptr; // 必须手动释放堆内存
}

关键陷阱

  • C/C++ 栈变量离开作用域立即销毁
  • 忘记 delete 会导致内存泄漏(JS 无此问题)

4. 指针基础

JavaScript (无指针)

let obj = { data: 10 };
let ref = obj;       // 引用传递
ref.data = 20;       // 原对象被修改

C (原始指针)

int main() {
    int a = 10;
    int* ptr = &a;    // ptr 存储 a 的地址
    *ptr = 20;        // 解引用修改值
    printf("%d", a);  // 输出 20

    int arr[3] = {1,2,3};
    int* p = arr;     // 数组名即首地址
    printf("%d", *(p+1)); // 输出 2
}

C++ (指针 + 引用)

int main() {
    int a = 10;
    int& ref = a;     // 引用(别名)
    ref = 20;         // 直接修改 a

    int* ptr = &a;    // 指针
    *ptr = 30;        // 通过指针修改

    // 对比 JS 的引用行为:
    std::vector<int> v1{1,2,3};
    auto& v2 = v1;    // 引用,类似 JS 的对象引用
    v2[0] = 99;       // 修改原容器
}

核心概念

  • & 获取地址,* 解引用
  • C++ 引用 (int&) 是安全指针,不可空且无需解引用
  • JS 对象传递本质是引用传递(类似指针)

5. 函数系统对比

JavaScript (灵活参数)

function add(a, b) {
    return a + b;
}
add(1, "2"); // "12"(隐式类型转换)

C (无重载)

int add(int a, int b) {
    return a + b;
}
// double add(double a, double b) { ... } // 编译错误:函数名冲突

C++ (函数重载 + 引用传参)

int add(int a, int b) { return a + b; }
double add(double a, double b) { return a + b; } // 重载合法

void swap(int& a, int& b) { // 引用传参
    int tmp = a;
    a = b;
    b = tmp;
}

int main() {
    int x = 1, y = 2;
    swap(x, y); // 直接修改原变量(类似 JS 对象传递)
}

JS 注意

  1. C++ 函数参数默认值传递(需要 & 实现引用传递)
  2. 函数重载是静态多态(JS 需手动检查参数类型)

6. 控制结构差异

switch 语句对比

// JavaScript (无 fall-through)
let val = 2;
switch(val) {
    case 1: console.log("A");
    case 2: console.log("B"); 
    // 不会执行下一个 case
    default: break;
}
// C/C++ (允许 fall-through)
int val = 2;
switch(val) {
    case 1: printf("A");
    case 2: printf("B"); // 输出 B 后继续执行
    case 3: printf("C"); // 会输出 C(需要 break)
    default: break;
}
// 输出结果: BC

本章小结

  • 核心差异:类型系统、内存管理、编译模型
  • 重点陷阱:指针误用、作用域生命周期、函数参数传递
  • 迁移技巧:用 auto 简化类型声明、优先使用引用替代原始指针

Tags:

最近发表
标签列表