当前位置: 首页 > news >正文

C++ 与其他编程语言区别_C++11/14/17新特性总结

C++11

decltype类型推导

decltype不依赖于初始化,根据表达式类推导类型

  • auto b :根据右边a的初始值来推导出变量的类型,然后将该初始值赋给b
  • decltype 则是根据a表达式来推导类型,变量的初始值与表达式的值无关
  • 表达式类型注意点:如果表达式是左值,则推导出的类型也是左值引用

 

int a = 10;
auto b = a;
decltype(a) b = a; // b的类型是intint add(int a, int b) {return a + b;
}decltype(add(1, 2)) result; // result的类型是intint x = 5;
int& ref = x;
decltype(ref) newRef = x; // newRef的类型是int&int func(int a, int b) {return a + b;
}decltype(&func) funcPtr = &func; // funcPtr的类型是int (*)(int, int)

bind

基本语法

  • callable:可以是函数指针、成员函数指针、函数对象或 lambda 表达式。
  • arg1, arg2, ..., argN:指定参数,可以是具体的值,也可以是占位符(例如 std::placeholders::_1
  • 占位符
    • 在使用 std::bind 时,可以使用占位符来表示绑定函数的参数位置。占位符定义在 std::placeholders 命名空间中,通常用 _1_2 等表示。例如:

    • std::placeholders::_1 表示绑定函数的第一个参数。
    • std::placeholders::_2 表示绑定函数的第二个参数
  • 注意
    • 参数绑定顺序std::bind 会按照传递给它的参数顺序进行绑定。占位符的编号必须与实际参数的位置相对应。
    • 捕获外部变量:使用 std::bind 时,可以将外部变量作为绑定参数传递,从而实现闭包效果。
    • 返回类型推导std::bind 创建的函数对象会自动推导返回类型,无需显式指定

绑定成员函数(常用) 

 

#include <iostream>
#include <functional>class MyClass {
public:void print_message(const std::string& message) {std::cout << "Message: " << message << std::endl;}
};int main() {MyClass my_object;// 绑定成员函数auto bound_member_function = std::bind(&MyClass::print_message, &my_object, std::placeholders::_1);bound_member_function("Hello, World!"); // 输出:Message: Hello, World!return 0;
}

绑定函数 

#include <iostream>
#include <functional>void print_sum(int a, int b) {std::cout << "Sum: " << a + b << std::endl;
}int main() {// 绑定参数到具体值auto bound_print = std::bind(print_sum, 5, 3);bound_print(); // 输出:Sum: 8// 使用占位符auto bound_print_with_placeholder = std::bind(print_sum, std::placeholders::_1, 10);bound_print_with_placeholder(5); // 输出:Sum: 15return 0;
}

绑定函数对象 

#include <iostream>
#include <functional>struct Multiply {int operator()(int a, int b) const {return a * b;}
};int main() {Multiply multiply;// 绑定函数对象auto bound_multiply = std::bind(multiply, std::placeholders::_1, 4);std::cout << "Product: " << bound_multiply(5) << std::endl; // 输出:Product: 20return 0;
}

范围for

  •  作用:遍历容器中的数据
  • 参数
    • declaration:用于声明每次迭代中从容器中提取的元素,可以是变量或引用。
    • expression:表示需要遍历的容器或范围
  • 注意点
    • 自动推导类型,可以使用auto关键字自动推导元素类型
    • 如果不需要修改容器中的元素,最后使用const声明元素,避免容器中的数据被修改
    • 范围:任何可以使用begin 和 end 的容器

 

事例代码 

 

#include <iostream>
#include <vector>int main() {std::vector<int> vec = {1, 2, 3, 4, 5};// 使用引用遍历并修改元素for (int& elem : vec) {elem *= 2;}for (int elem : vec) {std::cout << elem << " ";}std::cout << std::endl;return 0;
}

右值引用

左值与右值

  • 左值:持久存储的对象,通常是变量
  • 右值:没有持久存储的临时对象,一般都是临时变量

用法:move可以显式的将一个左值转换为对应的右值引用类型

 

右值引用与移动语义结合事例代码

#include <iostream>
#include <vector>
#include <string>class Resource {
public:std::string name;std::vector<int> data;Resource(const std::string& name) : name(name) {std::cout << "Constructing " << name << std::endl;}Resource(const Resource& other) : name(other.name), data(other.data) {std::cout << "Copy Constructing " << name << std::endl;}Resource(Resource&& other) noexcept : name(std::move(other.name)), data(std::move(other.data)) {std::cout << "Move Constructing " << name << std::endl;}Resource& operator=(Resource&& other) noexcept {if (this != &other) {name = std::move(other.name);data = std::move(other.data);std::cout << "Move Assigning " << name << std::endl;}return *this;}
};int main() {Resource res1("Resource1");Resource res2("Resource2");// 触发移动构造函数Resource res3 = std::move(res1);// 触发移动赋值运算符res2 = std::move(res3);return 0;
}

标准库move函数

用法总结

  • 作用:将参数显式的转换为一个右值引用,使对象可以通过移动而不是复制的方式传递或者返回,从而提高程序性能(例如在动态内存等场景中,让资源空间移动,可以避免复制开辟空间的性能消耗
  • 理解:提供一个移动资源的方法
  • 实现:将其参数转换为右值引用

使用代码事例

#include <iostream>
#include <vector>
#include <utility> // for std::moveint main() {std::vector<int> v1 = { 1, 2, 3, 4, 5 };std::vector<int> v2;// 使用 std::move 将 v1 转换为右值引用,从而启用移动语义v2 = std::move(v1);// 现在 v1 应该是空的,v2 持有原先 v1 的资源std::cout << "v1 size: " << v1.size() << std::endl;std::cout << "v2 size: " << v2.size() << std::endl;return 0;
}

如果想要对象支持移动语义,则需要的为其定义移动构造函数以及移动赋值运算符 

class MyClass {
public:MyClass() : data(new int[100]) {}~MyClass() { delete[] data; }// 移动构造函数MyClass(MyClass&& other) noexcept : data(other.data) {other.data = nullptr;}// 移动赋值运算符MyClass& operator=(MyClass&& other) noexcept {if (this != &other) {delete[] data;data = other.data;other.data = nullptr;}return *this;}// 禁用复制构造函数和复制赋值运算符MyClass(const MyClass&) = delete;MyClass& operator=(const MyClass&) = delete;private:int* data;
};

禁用对象默认函数

C++11中如果不希望对象被复制,可以将复制构造函数以及复制赋值函数声明为delete来禁用,移动构造和移动赋值同样适用。C++11之前,可以将对象的默认函数放入私有域中,从而达到禁止使用默认函数的功能。

代码事例:C++11中的做法,以及private禁止默认函数的做法

class MyClass {
public:MyClass() = default;~MyClass() = default;// 禁用复制构造函数MyClass(const MyClass&) = delete;// 禁用复制赋值运算符MyClass& operator=(const MyClass&) = delete;// 禁用移动构造函数MyClass(MyClass&&) = delete;// 禁用移动赋值运算符MyClass& operator=(MyClass&&) = delete;
};
class MyClass {
public:MyClass() {}~MyClass() {}private:// 禁用复制构造函数MyClass(const MyClass&);// 禁用复制赋值运算符MyClass& operator=(const MyClass&);// 禁用移动构造函数MyClass(MyClass&&);// 禁用移动赋值运算符MyClass& operator=(MyClass&&);
};

constexpr

该关键字用于指示表达式或者函数在编译的时候求职,用于定义常量表达式,从而提高程序的效率和安全性。

constexpr变量

  • 编译时求值的常量
  • constexpr确保在编译时进行求值,而const只可以确保值不能在运行中改变
constexpr int square(int x) {return x * x;
}int main() {constexpr int a = 10;constexpr int b = square(a); // 在编译时求值int arr[b]; // 使用编译时常量作为数组大小return 0;
}

constexpr函数

  • 该函数是在编译时求值
  • 使用条件
    • 函数的返回类型以及参数必须是字面值类型
    • 函数体中只可以包含单一的return语句(注意,该规定在C++14中更改了)

constexpr int factorial(int n) {return (n <= 1) ? 1 : (n * factorial(n - 1));
}int main() {constexpr int result = factorial(5); // 在编译时计算 5 的阶乘static_assert(result == 120, "Factorial calculation is incorrect");return 0;
}

constexpr 与 const的区别

  • const确保变量在运行的时候是只读的,但不一定在编译的时候求值
  • constexpr确保表达式在编译时求值,并且变量在运行的时候是只读 

const int a = 10; // 运行时常量
constexpr int b = 10; // 编译时常量const int x = factorial(a); // 可以在运行时计算
constexpr int y = factorial(b); // 必须在编译时计算

初始化列表 initializer list

用法总结

  • 语法使用:直接初始化成员变量,而不用在构造函数体内赋值
  • 特点
    • 优化性能,减少性能开销
    • const成员变量必须通过初始化列表进行初始化,因为const成员变量在构造完成后不可以被赋值
    • 引用成员也必须通过初始化列表进行初始化
    • 顺序列表中的初始化的顺序必须和类中声明顺序一致
class MyClass {
public:MyClass(int a, int b) : x(a), y(b), z(a + b), ref(a) {}
private:const int x;int y;int z;int& ref;
};

nullptr

用法总结

  • 作用:C++11之前使用NULL宏来表示,NULL宏被定义为整数0,容易在上下文中引起歧义;nullptr则是一个指针字面值,专门用于表示空指针,不存在歧义问题
  • 优点
    • 类型安全:nullptr是一个指针类型,所以不会与整数类型混淆
    • 函数重载的时候,nullptr可以帮忙区分指针和整数参数

C++14

函数返回值类型推导

  • 作用:允许编译器根据函数返回语句,自动推导出返回类型,下面案例是自动推导出int类型
  • 注意
    • 单一返回类型:函数中所有返回语句必须是相同类型,否则编译器会报错
    • 返回引用和指针的时候,需要确保返回的对象在作用域中是否有效,避免悬空引用
#include <iostream>auto add(int a, int b) {return a + b;
}int main() {std::cout << add(2, 3) << std::endl; // 输出 5return 0;
}

lambda函数形参允许泛型

作用:无需预先指定参数类型,编译器根据lambda的使用情况自动推导参数的类型

 

事例案例理解 

#include <iostream>int main() {auto add = [](auto x, auto y) {return x + y;};std::cout << add(1, 2) << std::endl;       // 输出 3std::cout << add(1.5, 2.5) << std::endl;   // 输出 4.0std::cout << add(std::string("Hello, "), std::string("World!")) << std::endl; // 输出 Hello, World!return 0;
}
#include <iostream>
#include <vector>
#include <algorithm>int main() {int factor = 2;auto multiply = [factor](auto x) {return x * factor;};std::cout << multiply(3) << std::endl;    // 输出 6std::cout << multiply(3.5) << std::endl;  // 输出 7.0return 0;
}
#include <iostream>
#include <vector>
#include <algorithm>int main() {std::vector<int> vec = {1, 2, 3, 4, 5};auto print = [](const auto& container) {for (const auto& elem : container) {std::cout << elem << " ";}std::cout << std::endl;};print(vec); // 输出 1 2 3 4 5return 0;
}

变量模板

作用:类似于函数模板,但是是给变量使用的一种模板

#include <iostream>template<typename T>
constexpr T pi = T(3.1415926535897932385);int main() {std::cout << pi<float> << std::endl;  // 输出 3.14159std::cout << pi<double> << std::endl; // 输出 3.141592653589793std::cout << pi<long double> << std::endl; // 输出 3.1415926535897932385return 0;
}

常量模版,事例中是获取不同类型的最大值 

#include <iostream>template<typename T>
constexpr T max_value = std::numeric_limits<T>::max();int main() {std::cout << max_value<int> << std::endl;          // 输出 int 类型的最大值std::cout << max_value<unsigned int> << std::endl; // 输出 unsigned int 类型的最大值std::cout << max_value<double> << std::endl;       // 输出 double 类型的最大值return 0;
}

属性模版,下面事例展示用于计算的给定类型的平方根 

#include <iostream>
#include <cmath>template<typename T>
constexpr T square(T x) {return x * x;
}template<typename T>
constexpr T sqrt_value = std::sqrt(square(T(2)));int main() {std::cout << sqrt_value<float> << std::endl;  // 输出 2.82843std::cout << sqrt_value<double> << std::endl; // 输出 2.82843std::cout << sqrt_value<long double> << std::endl; // 输出 2.82843return 0;
}

类模版和变量模板

#include <iostream>template<typename T>
struct Traits {static constexpr T zero = T(0);
};int main() {std::cout << Traits<int>::zero << std::endl;       // 输出 0std::cout << Traits<float>::zero << std::endl;     // 输出 0std::cout << Traits<double>::zero << std::endl;    // 输出 0return 0;
}

deprecated属性

作用:标记不建议使用的函数、变量或者类型,如果使用了,则编译的时候会报错

 标记函数被弃用

#include <iostream>[[deprecated]]
void oldFunction() {std::cout << "This is an old function." << std::endl;
}void newFunction() {std::cout << "This is a new function." << std::endl;
}int main() {oldFunction(); // 编译时会产生警告newFunction(); // 正常调用return 0;
}

标记变量弃用 

#include <iostream>[[deprecated("Use newVar instead")]]
int oldVar;int newVar;int main() {oldVar = 10; // 编译时会产生警告newVar = 20; // 正常使用std::cout << oldVar << std::endl;std::cout << newVar << std::endl;return 0;
}

标记类型弃用 

#include <iostream>[[deprecated("Use NewStruct instead")]]
struct OldStruct {int value;
};struct NewStruct {int value;
};int main() {OldStruct oldInstance; // 编译时会产生警告oldInstance.value = 10;NewStruct newInstance;newInstance.value = 20;std::cout << oldInstance.value << std::endl;std::cout << newInstance.value << std::endl;return 0;
}

标记类的成员函数被弃用 

#include <iostream>class MyClass {
public:[[deprecated("Use newMethod() instead")]]void oldMethod() {std::cout << "This is the old method." << std::endl;}void newMethod() {std::cout << "This is the new method." << std::endl;}
};int main() {MyClass obj;obj.oldMethod(); // 编译时会产生警告obj.newMethod(); // 正常调用return 0;
}

std::make_unique

  • 作用:用于创建std::unique_ptr对象,以一种更安全高效的方式创建智能指针,避免new的内存泄漏风险
  • 优点
    • 避免内存泄漏
    • 类型安全:会自动推导出指针类型,减少类型错误的风险
  • 语法分析
    • T 是要创建的对象的类型。
    • Args&&... args 是传递给 T 的构造函数的参数

 创建一个对象:创建一个指向整数42的unique_ptr

#include <iostream>
#include <memory>int main() {auto p = std::make_unique<int>(42);std::cout << *p << std::endl; // 输出 42return 0;
}

 创建动态数组

#include <iostream>
#include <memory>int main() {auto p = std::make_unique<int[]>(5);for (int i = 0; i < 5; ++i) {p[i] = i * i;}for (int i = 0; i < 5; ++i) {std::cout << p[i] << " "; // 输出 0 1 4 9 16}std::cout << std::endl;return 0;
}

创建自定义对象

#include <iostream>
#include <memory>class MyClass {
public:MyClass(int x) : x_(x) {std::cout << "MyClass constructed with " << x_ << std::endl;}~MyClass() {std::cout << "MyClass destructed" << std::endl;}int getX() const { return x_; }private:int x_;
};int main() {auto p = std::make_unique<MyClass>(10);std::cout << p->getX() << std::endl; // 输出 10return 0;
}

C++17

结构化绑定

作用:通过简单的语法,实现将变量绑定到结构或者元祖的成员上

 

解构元组

#include <iostream>
#include <tuple>std::tuple<int, double, std::string> getTuple() {return {1, 2.5, "hello"};
}int main() {auto [x, y, z] = getTuple();std::cout << "x: " << x << ", y: " << y << ", z: " << z << std::endl;return 0;
}

解构结构体

#include <iostream>struct Point {int x;int y;
};int main() {Point p{10, 20};auto [x, y] = p;std::cout << "x: " << x << ", y: " << y << std::endl;return 0;
}

解构数组 

#include <iostream>int main() {int arr[] = {1, 2, 3};auto [a, b, c] = arr;std::cout << "a: " << a << ", b: " << b << ", c: " << c << std::endl;return 0;
}

 与标准库结合使用

#include <iostream>
#include <map>int main() {std::map<int, std::string> m = {{1, "one"}, {2, "two"}, {3, "three"}};for (const auto& [key, value] : m) {std::cout << "key: " << key << ", value: " << value << std::endl;}return 0;
}

if-switch语句初始化

含义:允许在if 和switch语句中进行初始化,从而让变量的作用域更加局部化(根据具体事例理解)

 if语句初始化(auto it ...初始化,只在if语句范围内有用)

 

#include <iostream>
#include <vector>int main() {std::vector<int> vec = {1, 2, 3, 4, 5};if (auto it = std::find(vec.begin, vec.end(), 3); it != vec.end()) {std::cout << "Found 3 at index " << std::distance(vec.begin(), it) << std::endl;} else {std::cout << "3 not found" << std::endl;}return 0;
}

Switch语句初始化,也同样只在Switch语句范围内起作用 

#include <iostream>
#include <map>enum class Color { RED, GREEN, BLUE };int main() {std::map<std::string, Color> colorMap = {{"red", Color::RED}, {"green", Color::GREEN}, {"blue", Color::BLUE}};std::string colorStr = "green";switch (auto it = colorMap.find(colorStr); it != colorMap.end() ? it->second : Color::BLUE) {case Color::RED:std::cout << "Color is red" << std::endl;break;case Color::GREEN:std::cout << "Color is green" << std::endl;break;case Color::BLUE:std::cout << "Color is blue" << std::endl;break;default:std::cout << "Unknown color" << std::endl;break;}return 0;
}

constexpr lambda表达式

总结

  • 该lambda表达式可以在编译的时候进行常量计算,从而提高代码效率和安全性。
  • 注意
    • 表达式限制: constexpr lambda表达式中的代码必须符合constexpr函数的要求
    • 常量上下文:该lambda表达式必须能够在编译的时候计算

#include <iostream>constexpr auto add = [](int a, int b) constexpr {return a + b;
};int main() {constexpr int result = add(3, 4); // 在编译时计算std::cout << "Result: " << result << std::endl; // 输出 7return 0;
}

常量计算 

#include <iostream>
#include <array>constexpr auto square = [](int x) constexpr {return x * x;
};int main() {constexpr int value = 5;constexpr int result = square(value); // 在编译时计算std::array<int, result> arr; // 使用计算结果作为数组大小std::cout << "Array size: " << arr.size() << std::endl; // 输出 25return 0;
}

与标准库结合使用的场景 

#include <iostream>
#include <algorithm>
#include <array>int main() {constexpr auto greater = [](int a, int b) constexpr {return a > b;};std::array<int, 5> arr = {5, 2, 3, 4, 1};std::sort(arr.begin(), arr.end(), greater); // 在运行时排序for (const auto& elem : arr) {std::cout << elem << " "; // 输出 5 4 3 2 1}std::cout << std::endl;return 0;
}

namespace嵌套

基于语法结构

#include <iostream>namespace Outer {int outerVar = 10;namespace Inner {int innerVar = 20;class InnerClass {public:void display() {std::cout << "Outer variable: " << outerVar << std::endl;std::cout << "Inner variable: " << innerVar << std::endl;}};}
}int main() {Outer::Inner::InnerClass obj;obj.display();return 0;
}

#include <iostream>namespace Outer {int outerVar = 10;namespace Inner {int innerVar = 20;class InnerClass {public:void display() {std::cout << "Outer variable: " << outerVar << std::endl;std::cout << "Inner variable: " << innerVar << std::endl;}};}
}int main() {Outer::Inner::InnerClass obj;obj.display();return 0;
}

std::any

总结

  • 含义:提供一种类型安全的方式来存储和操作任意类型的值(可以理解成动态语言中的万能类型)
  • 使用场景:用来代替一些需要存储不同类型对象的场景
  • 事例代码
    • 定义和使用any类型定义的数值
    • 访问存储的数值
    • 检查any中的类型(type())
#include <iostream>
#include <any>int main() {std::any a = 1; // 存储 int 类型std::cout << std::any_cast<int>(a) << std::endl;a = 3.14; // 存储 double 类型std::cout << std::any_cast<double>(a) << std::endl;a = std::string("Hello, std::any!"); // 存储 std::string 类型std::cout << std::any_cast<std::string>(a) << std::endl;return 0;
}
#include <iostream>
#include <any>int main() {std::any a = 10;try {int value = std::any_cast<int>(a);std::cout << "Value: " << value << std::endl;} catch (const std::bad_any_cast& e) {std::cout << "Bad any_cast: " << e.what() << std::endl;}return 0;
}
#include <iostream>
#include <any>
#include <typeinfo>int main() {std::any a = 10;if (a.type() == typeid(int)) {std::cout << "a contains an int" << std::endl;} else {std::cout << "a does not contain an int" << std::endl;}return 0;
}

std::basic_string_view

总结

  • 作用:轻量级、非拥有的字符串视图类型,对字符串只读访问,也就是只查看字符串指定内容,不需要复制或者拥有字符串的实际数据
  • 特点
    • 轻量级:只是一个视图,不拥有数据,所以构造和赋值的性能开销小
    • 无拷贝:因为不需要数据,所以不会进行数据拷贝
    • 灵活:可以按照自己的需要灵活拷贝字符串
#include <iostream>
#include <string_view>void printString(std::string_view sv) {std::cout << sv << std::endl;
}int main() {std::string str = "Hello, std::string_view!";printString(str); // 传递 std::stringprintString("Hello, world!"); // 传递字符串字面量printString(str.substr(7, 12)); // 传递 std::string 的子字符串return 0;
}

//基本操作#include <iostream>
#include <string_view>int main() {std::string_view sv = "Hello, world!";std::cout << "Length: " << sv.length() << std::endl; // 输出长度std::cout << "First character: " << sv.front() << std::endl; // 输出第一个字符std::cout << "Last character: " << sv.back() << std::endl; // 输出最后一个字符std::cout << "Substring: " << sv.substr(7, 5) << std::endl; // 输出子字符串 "world"// 查找子字符串size_t pos = sv.find("world");if (pos != std::string_view::npos) {std::cout << "\"world\" found at position " << pos << std::endl;}return 0;
}

#include <iostream>
#include <string_view>int main() {std::string_view sv = "Hello, world!";std::cout << "Length: " << sv.length() << std::endl; // 输出长度std::cout << "First character: " << sv.front() << std::endl; // 输出第一个字符std::cout << "Last character: " << sv.back() << std::endl; // 输出最后一个字符std::cout << "Substring: " << sv.substr(7, 5) << std::endl; // 输出子字符串 "world"// 查找子字符串size_t pos = sv.find("world");if (pos != std::string_view::npos) {std::cout << "\"world\" found at position " << pos << std::endl;}return 0;
}

C和C++

相同点

  • 基本语法结构,循环控制函数定义都类似
  • 基本数据结构
  • C中的标准库函数在C++中同样适用
  • 指针与数组使用方法类似
  • 预处理指令

不同点

  • 面向对象:C++支持面向对象
  • 函数与运算符重载:C++支持,C不支持
  • 模板:C++支持
  • C++支持STL标准库
  • 两者的内存管理不同C++有异常处理机制,但是C没有

Java和C++

相同点

  • 面向对象编程

    • 两者都支持面向对象编程,包括类、继承、多态、封装等概念。
  • 语法结构

    • 两者的基本语法结构相似,如 if-elsefor 循环、while 循环、switch 语句等
  • 基本数据类型

    • 都有基本数据类型,如 intcharfloatdouble 等。
  • 标准库支持

    • 两者都提供了丰富的标准库,用于字符串操作、输入输出、集合等

不同点

  • 内存管理

    • C++ 需要手动进行内存管理,使用 newdelete 进行动态内存分配和释放。
    • Java 有垃圾回收机制,自动管理内存。
  • 平台独立性

    • C++ 编译生成的可执行文件是平台相关的。
    • Java 编译生成字节码,运行在 Java 虚拟机(JVM)上,实现平台独立性。
  • 多重继承

    • C++ 支持多重继承。
    • Java 不支持多重继承,但可以通过接口实现类似效果。
  • 指针

    • C++ 直接支持指针。
    • Java 不直接支持指针,提供了引用类型。
  • 异常处理

    • Java 强制使用异常处理,许多库函数都会抛出异常。
    • C++ 提供异常处理机制,但使用不如 Java 强制。
  • 模板与泛型

    • C++ 使用模板实现泛型编程。
    • Java 使用泛型,但类型信息在运行时会被擦除(类型擦除)

Python和C++

相同点

  • 支持面向对象编程

    • 两者都支持面向对象编程。
  • 丰富的标准库

    • 两者都提供了丰富的标准库支持多种功能

不同点

  • 语法和易用性

    • Python 语法简单易读,强调代码的可读性。
    • C++ 语法复杂,更加灵活,但也更容易出现错误。
  • 性能

    • C++ 是编译型语言,性能高,适合对性能要求高的系统编程。
    • Python 是解释型语言,性能较低,但开发速度快,适合快速开发和脚本编写。
  • 内存管理

    • C++ 手动管理内存。
    • Python 有自动垃圾回收机制。
  • 类型系统

    • C++ 是静态类型语言,编译时检查类型。
    • Python 是动态类型语言,运行时检查类型。
  • 并发与并行

    • C++ 提供了多线程和多进程的并发机制。
    • Python 也支持多线程和多进程,但由于全局解释器锁(GIL)的存在,多线程性能受限,多进程更常用。
  • 应用领域

    • C++ 常用于系统编程、游戏开发、嵌入式系统等。
    • Python 常用于数据分析、机器学习、Web 开发、自动化脚本等

Go和C++

相同点

  • 编译型语言:源代码在执行前需要编译成可执行文件
  • 编译时对类型进行检查
  • 支持标准库,比如文件操作或者网络编程等

不同点

  •  语法
    • Go语法简洁,代码可读性高
    • C++语法复杂,功能强大,但是容易导致代码冗长难以维护
  • 内存管理
    • Go有垃圾回收机制,自动管理内存
    • C++需要手动管理内存
  • 并发编程
    • Go内置强大的并发支持,可以通过goroutines和channels实现并发
    • C++的多线程编程较为麻烦
  • 编译时间
    • Go变异速度快,适合快速开发和部署
    • C++编译速度慢
  • 错误处理

    • Go 使用显式错误处理,通过返回值和 error 类型处理错误。
    • C++ 使用异常处理机制,通过 try-catch 块捕获和处理异常。
  • 面向对象编程

    • C++ 是面向对象语言,支持类、继承、多态等特性。
    • Go 支持面向对象编程,但没有类和继承,使用结构体和接口实现类似功能

Rust和C++

相同点

  •  编译型语言,代码执行前都需要编译成可执行文件
  • 强类型检查,编译的时候都会进行类型检查
  • 都对底层硬件和内存进行精细控制,适合系统编程和高性能应用

不同点

  • 内存管理
    • C++需要程序员管理内存,通常需要使用new和delete进行动态内存分配和释放
    • Rust则使用所有权系统和借助检查器管理内存,编译的时候保证内存安全,无需垃圾回收
  • 并发编程
    • Rust提供了安全的并发编程,通过所有权和类型系统在编译的时候防止数据竞争
    • C++支持多线程编程,但是需要使用更复杂的线程库和同步机制
  •  错误处理
    • Rust使用显式错误处理,通过Result和Option类型来处理错误
    • C++使用异常处理机制,通过try-catch模块来捕捉异常
  • 面向对象
    • C++支持面向对象语言,支持类、继承、多态等
    • Rust则不支持传统的面向对象编程,但是提供结构体和特征来实现类似功能 

 

 

相关文章:

C++ 与其他编程语言区别_C++11/14/17新特性总结

C11 decltype类型推导 decltype不依赖于初始化&#xff0c;根据表达式类推导类型 auto b &#xff1a;根据右边a的初始值来推导出变量的类型&#xff0c;然后将该初始值赋给bdecltype 则是根据a表达式来推导类型&#xff0c;变量的初始值与表达式的值无关表达式类型注意点&…...

玩转云服务:Google Cloud谷歌云永久免费云服务器「白嫖」 指南

前几天&#xff0c;和大家分享了&#xff1a; 玩转云服务&#xff1a;Oracle Cloud甲骨文永久免费云服务器注册及配置指南 相信很多同学都卡在了这一步&#xff1a; 可用性域 AD-1 中配置 VM.Standard.E2.1.Micro 的容量不足。请在其他可用性域中创建实例&#xff0c;或稍后…...

用18讲必看:宇哥亲划重点内容+核心题总结

25考研结束之后&#xff0c;张宇老师的风评可能会两极分化 其中一波把张宇老师奉为考研数学之神&#xff0c;吹捧「三向解题法」天下无敌。 另外一波对张宇老师的评价负面&#xff0c;在网上黑张宇老师&#xff01; 为什么会这么说&#xff0c;因为张宇老师的新版36讲争议太…...

什么是安全生产痕迹化管理?如何做到生产过程中全程痕迹化管理?

安全生产痕迹化管理&#xff0c;简单来说&#xff0c;就是通过记录一些“信息”来确保安全工作的进展。这些方法包括记会议内容、写安全日记、拍照片、签字盖章、指纹识别、面部识别还有手机定位等。记录下来的文字、图片、数据和视频&#xff0c;就像一个个“脚印”&#xff0…...

VIsual Studio:为同一解决方案下多个项目分别指定不同的编译器

一、引言 如上图&#xff0c;我有一个解决方案【EtchDevice】&#xff0c;他包含两个&#xff08;甚至更多个&#xff09;子项目&#xff0c;分别是【DeviceRT】和【DeviceWin】&#xff0c;见名知意&#xff0c;我需要一个项目编译运行在RTOS上&#xff0c;譬如一个名叫INTime…...

Flat Ads资讯:Meta、Google、TikTok 7月产品政策速递

Flat Ads拥有全球媒介采买(MediaBuy)业务,为方便广告主及时了解大媒体最新政策,Flat Ads将整理大媒体产品更新月报,欢迎大家关注我们及时了解最新行业动向。 一、Meta 1、Reels 应用推广现可突出显示应用评分、点评和下载量 为了不断优化 Instagram 上的广告体验和广告表现,…...

嵌入式C++、ROS 、OpenCV、SLAM 算法和路径规划算法:自主导航的移动机器人流程设计(代码示例)

在当今科技迅速发展的背景下&#xff0c;嵌入式自主移动机器人以其广泛的应用前景和技术挑战吸引了越来越多的研究者和开发者。本文将详细介绍一个嵌入式自主移动机器人项目&#xff0c;涵盖其硬件与软件系统设计、代码实现及项目总结&#xff0c;并提供相关参考文献。 项目概…...

数据安全堡垒:SQL Server数据库备份验证与测试恢复全攻略

数据安全堡垒&#xff1a;SQL Server数据库备份验证与测试恢复全攻略 在数据库管理中&#xff0c;备份是确保数据安全的关键环节&#xff0c;但仅仅拥有备份是不够的&#xff0c;验证备份的有效性并能够从备份中成功恢复数据同样重要。SQL Server提供了一系列的工具和方法来执…...

嵌入式人工智能(40-基于树莓派4B的水滴传感器和火焰传感器)

虽然这两个传感器水火不容&#xff0c;我还是把他们放到一起了。本文是有线传感器的最后一个部分了。后面如果还有文章介绍有线传感器&#xff0c;也是补充学习其他内容不得已而为之。如果不是&#xff0c;就当我没说&#xff0c;哈哈。 1、水滴传感器 水滴传感器又称雨滴传感…...

EF访问PostgreSql,如何判断jsonb类型的数组是否包含某个数值

下面代码判断OpenUserIds&#xff08;long[]类型的jsonb&#xff09;字段&#xff0c;是否包含 8 basequery basequery.Where(m > Microsoft.EntityFrameworkCore.NpgsqlJsonDbFunctionsExtensions.JsonContains(EF.Functions, m.OpenUserIds, new long[] { 8 }));...

Qt 实战(8)控件 | 8.1、QComboBox

文章目录 一、QComboBox1、简介2、功能特性2.1、添加和移除项目2.2、设置和获取当前选中项2.3、模型/视图架构2.4、信号与槽 3、总结 前言&#xff1a; QComboBox 是 Qt 框架中一个非常实用的控件&#xff0c;它允许用户从一个下拉列表中选择一个项目。这个控件广泛应用于需要用…...

模拟算法概览

前言 LeetCode上的模拟算法题目主要考察通过直接模拟问题的实际操作和过程来解决问题。这类题目通常不需要高级的数据结构或复杂的算法&#xff0c;而是通过仔细的逻辑和清晰的步骤逐步解决。 适合解决的问题 模拟算法适合用来解决那些逻辑明确、步骤清晰且可以逐步执行的问…...

uniapp手写滚动选择器

文章目录 效果展示HTML/Template部分&#xff1a;JavaScript部分&#xff1a;CSS部分&#xff1a;完整代码 没有符合项目要求的选择器 就手写了一个 效果展示 实现一个时间选择器的功能&#xff0c;可以选择小时和分钟&#xff1a; HTML/Template部分&#xff1a; <picker…...

智慧医院临床检验管理系统源码(LIS),全套LIS系统源码交付,商业源码,自主版权,支持二次开发

实验室信息系统是集申请、采样、核收、计费、检验、审核、发布、质控、查询、耗材控制等检验科工作为一体的网络管理系统。它的开发和应用将加快检验科管理的统一化、网络化、标准化的进程。一体化设计&#xff0c;与其他系统无缝连接&#xff0c;全程化条码管理。支持危机值管…...

超市是怎样高效完成客流统计与客流分析

随着科技的进步&#xff0c;越来越多的超市开始采用现代化的客流统计系统来优化日常运营和提升顾客体验。本文将探讨超市客流统计面临的难题、客流统计系统的构成及其应用场景&#xff0c;以及系统如何通过高识别率和热力图分析等功能为超市带来实际效益。 一、景区客流统计难题…...

进程地址空间,零基础最最最详解

目录 建议全文阅读&#xff01;&#xff01;&#xff01; 建议全文阅读&#xff01;&#xff01;&#xff01; 建议全文阅读&#xff01;&#xff01;&#xff01; 一、什么是地址空间 1、概念 2、主要组成部分 3、特点和作用 &#xff08;1&#xff09;虚拟化&#xf…...

全面解锁:通过JSP和Ajax实现钉钉签到数据展示及部门筛选功能

要在JSP页面中调用钉钉的签到接口&#xff0c;并将签到数据展示在页面上&#xff0c;同时提供部门筛选功能&#xff0c;你可以按照以下步骤操作&#xff1a; 准备钉钉API&#xff1a; 你需要首先获取钉钉开放平台的API凭证&#xff08;如access_token&#xff09;。请参考钉钉开…...

LLM应用-prompt提示:让大模型总结生成PPT

参考&#xff1a; https://mp.weixin.qq.com/s/frKOjf4hb6yec8LzSmvQ7A 思路&#xff1a;通过大模型生成markdown内容&#xff0c;通过markdown去生成PPT 技术&#xff1a;Marp&#xff08;https://marp.app/&#xff09;这里用的这个工具进行markdown转PPT 1、让大模型生成Ma…...

安全防护软件的必要性:从微软蓝屏事件谈起

最近微软遭遇了的大规模蓝屏事件&#xff0c;让全球很多用户措手不及。这次事件告诉我们&#xff0c;保护我们的电脑和数据&#xff0c;安全防护软件是多么重要。 微软蓝屏事件源于网络安全公司CrowdStrike的技术更新错误&#xff0c;导致全球范围内大量Windows用户系统崩溃&a…...

解开基于大模型的Text2SQL的神秘面纱

你好&#xff0c;我是 shengjk1&#xff0c;多年大厂经验&#xff0c;努力构建 通俗易懂的、好玩的编程语言教程。 欢迎关注&#xff01;你会有如下收益&#xff1a; 了解大厂经验拥有和大厂相匹配的技术等 希望看什么&#xff0c;评论或者私信告诉我&#xff01; 文章目录 一…...

Spring Boot 实现流式响应(兼容 2.7.x)

在实际开发中&#xff0c;我们可能会遇到一些流式数据处理的场景&#xff0c;比如接收来自上游接口的 Server-Sent Events&#xff08;SSE&#xff09; 或 流式 JSON 内容&#xff0c;并将其原样中转给前端页面或客户端。这种情况下&#xff0c;传统的 RestTemplate 缓存机制会…...

【入坑系列】TiDB 强制索引在不同库下不生效问题

文章目录 背景SQL 优化情况线上SQL运行情况分析怀疑1:执行计划绑定问题?尝试:SHOW WARNINGS 查看警告探索 TiDB 的 USE_INDEX 写法Hint 不生效问题排查解决参考背景 项目中使用 TiDB 数据库,并对 SQL 进行优化了,添加了强制索引。 UAT 环境已经生效,但 PROD 环境强制索…...

深入理解JavaScript设计模式之单例模式

目录 什么是单例模式为什么需要单例模式常见应用场景包括 单例模式实现透明单例模式实现不透明单例模式用代理实现单例模式javaScript中的单例模式使用命名空间使用闭包封装私有变量 惰性单例通用的惰性单例 结语 什么是单例模式 单例模式&#xff08;Singleton Pattern&#…...

vue3 定时器-定义全局方法 vue+ts

1.创建ts文件 路径&#xff1a;src/utils/timer.ts 完整代码&#xff1a; import { onUnmounted } from vuetype TimerCallback (...args: any[]) > voidexport function useGlobalTimer() {const timers: Map<number, NodeJS.Timeout> new Map()// 创建定时器con…...

【Go语言基础【13】】函数、闭包、方法

文章目录 零、概述一、函数基础1、函数基础概念2、参数传递机制3、返回值特性3.1. 多返回值3.2. 命名返回值3.3. 错误处理 二、函数类型与高阶函数1. 函数类型定义2. 高阶函数&#xff08;函数作为参数、返回值&#xff09; 三、匿名函数与闭包1. 匿名函数&#xff08;Lambda函…...

A2A JS SDK 完整教程:快速入门指南

目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库&#xff…...

站群服务器的应用场景都有哪些?

站群服务器主要是为了多个网站的托管和管理所设计的&#xff0c;可以通过集中管理和高效资源的分配&#xff0c;来支持多个独立的网站同时运行&#xff0c;让每一个网站都可以分配到独立的IP地址&#xff0c;避免出现IP关联的风险&#xff0c;用户还可以通过控制面板进行管理功…...

Qt 事件处理中 return 的深入解析

Qt 事件处理中 return 的深入解析 在 Qt 事件处理中&#xff0c;return 语句的使用是另一个关键概念&#xff0c;它与 event->accept()/event->ignore() 密切相关但作用不同。让我们详细分析一下它们之间的关系和工作原理。 核心区别&#xff1a;不同层级的事件处理 方…...

如何把工业通信协议转换成http websocket

1.现状 工业通信协议多数工作在边缘设备上&#xff0c;比如&#xff1a;PLC、IOT盒子等。上层业务系统需要根据不同的工业协议做对应开发&#xff0c;当设备上用的是modbus从站时&#xff0c;采集设备数据需要开发modbus主站&#xff1b;当设备上用的是西门子PN协议时&#xf…...

MeshGPT 笔记

[2311.15475] MeshGPT: Generating Triangle Meshes with Decoder-Only Transformers https://library.scholarcy.com/try 真正意义上的AI生成三维模型MESHGPT来袭&#xff01;_哔哩哔哩_bilibili GitHub - lucidrains/meshgpt-pytorch: Implementation of MeshGPT, SOTA Me…...