为了账号安全,请及时绑定邮箱和手机立即绑定

C++11语法入门教程

标签:
C++
概述

本文详细介绍了C++11语法中的新特性,包括移动语义与右值引用、新的字符串和数字字面量、智能指针以及Lambda表达式等。文章还深入讲解了C++11中的auto关键字、range-based for循环和nullptr等语法基础,并展示了函数与对象、容器与算法、线程支持等多个方面的示例代码。

C++11新特性介绍

移动语义与右值引用

C++11引入了移动语义和右值引用,以提高资源管理的效率。通过移动语义,可以将资源从一个对象转移到另一个对象,而不需要进行深拷贝。右值引用(r-value reference)是实现这一功能的关键。右值引用通过&&符号表示。

示例代码

#include <iostream>
#include <string>

class String {
public:
    String(const std::string& str) : data(new std::string(str)) {}
    String(String&& other) noexcept : data(other.data) {
        other.data = nullptr;
    }
    ~String() { delete data; }

    String& operator=(String&& other) noexcept {
        if (this != &other) {
            delete data;
            data = other.data;
            other.data = nullptr;
        }
        return *this;
    }

private:
    std::string* data;
};

int main() {
    String s1("Hello, World!");
    String s2 = std::move(s1); // 使用移动语义
    std::cout << *s2.data << std::endl;
    return 0;
}

新的字符串和数字字面量

C++11引入了新的字符串和数字字面量,使代码更简洁。这包括原始字符串字面量、十六进制浮点数等。

示例代码

#include <iostream>

int main() {
    // 原始字符串字面量
    const char* str = R"(This is a "raw string" with \n in it.)";
    std::cout << str << std::endl;

    // 十六进制浮点数
    double d1 = 0x1.23p10;
    std::cout << d1 << std::endl;

    // 十六进制整数
    int hex = 0x12345678;
    std::cout << hex << std::endl;

    return 0;
}

智能指针

C++11引入了智能指针,如std::unique_ptrstd::shared_ptr,以简化内存管理。std::unique_ptr提供了独占所有权的智能指针,而std::shared_ptr则允许多个指针共享一个对象的生命周期。

示例代码

#include <iostream>
#include <memory>

int main() {
    // 使用 std::unique_ptr
    std::unique_ptr<int> ptr1(new int(10));
    std::cout << *ptr1 << std::endl;

    // 使用 std::shared_ptr
    std::shared_ptr<int> ptr2 = std::make_shared<int>(20);
    std::cout << *ptr2 << std::endl;

    // 复制 shared_ptr
    std::shared_ptr<int> ptr3 = ptr2;
    std::cout << *ptr3 << std::endl;

    return 0;
}

Lambda表达式

Lambda表达式允许在代码中定义匿名函数。这对于编写简洁、可读性高的代码非常有用。

示例代码

#include <iostream>
#include <vector>
#include <algorithm>

int main() {
    std::vector<int> v = {1, 2, 3, 4, 5};

    // 使用 Lambda 表达式
    auto is_even = [](int x) { return x % 2 == 0; };
    std::vector<int> even_numbers;
    std::copy_if(v.begin(), v.end(), std::back_inserter(even_numbers), is_even);

    for (int num : even_numbers) {
        std::cout << num << " ";
    }
    std::cout << std::endl;

    return 0;
}
C++11语法基础

auto关键字

auto关键字允许编译器自动推断变量类型,从而简化代码。这在处理复杂类型时尤其有用。

示例代码

#include <iostream>
#include <vector>

int main() {
    std::vector<int> v = {1, 2, 3, 4, 5};

    // 使用 auto 关键字
    auto sum = 0;
    for (auto it = v.begin(); it != v.end(); ++it) {
        sum += *it;
    }

    std::cout << "Sum: " << sum << std::endl;

    return 0;
}

range-based for循环

range-based for循环允许更简洁地遍历容器中的元素。这种循环不需要显式使用迭代器。

示例代码

#include <iostream>
#include <vector>

int main() {
    std::vector<int> v = {1, 2, 3, 4, 5};

    // 使用 range-based for 循环
    for (int value : v) {
        std::cout << value << " ";
    }
    std::cout << std::endl;

    return 0;
}

decltype关键字

decltype关键字用于获取变量或表达式的类型。这在模板元编程中特别有用。

示例代码

#include <iostream>

int main() {
    int x = 5;

    // 使用 decltype
    decltype(x) y = 10;
    std::cout << "x 的类型是: " << typeid(decltype(x)).name() << std::endl;
    std::cout << "y 的类型是: " << typeid(decltype(y)).name() << std::endl;

    return 0;
}

nullptr

nullptr是一个专门用于空指针的常量,取代了传统的NULL定义,以提高代码的安全性和可读性。

示例代码

#include <iostream>

int main() {
    int* ptr = nullptr;

    if (ptr == nullptr) {
        std::cout << "ptr 是空指针" << std::endl;
    }

    return 0;
}
C++11中的函数与对象

异常处理改进

C++11增强了异常处理的能力,包括新的noexcept关键字和std::terminate函数。noexcept用于声明函数不会抛出异常,而std::terminate用于处理未捕获的异常。

示例代码

#include <iostream>
#include <exception>

void func() noexcept {
    throw std::runtime_error("Exception occurred");
}

int main() {
    try {
        func();
    } catch (const std::exception& e) {
        std::cout << "Caught an exception: " << e.what() << std::endl;
    }

    return 0;
}

类型推断与模板推导

C++11引入了类型推断,使得模板推导更加灵活。这在使用模板函数和类时特别有用。

示例代码

#include <iostream>
#include <type_traits>

template<typename T>
void printType(const T& value) {
    std::cout << "类型是: " << typeid(T).name() << std::endl;
}

int main() {
    int x = 10;
    std::string str = "Hello, World!";

    printType(x);
    printType(str);

    return 0;
}

类成员初始化

C++11允许在类的构造函数中直接初始化成员变量,简化了代码的编写。

示例代码

#include <iostream>

class MyClass {
public:
    MyClass(int x, std::string y) : value(x), message(y) {}

    void print() {
        std::cout << "Value: " << value << ", Message: " << message << std::endl;
    }

private:
    int value;
    std::string message;
};

int main() {
    MyClass obj(10, "Hello, World!");
    obj.print();

    return 0;
}
C++11中的容器与算法

新增的容器类型

C++11引入了几个新的标准库容器,如std::unordered_setstd::unordered_map,这些容器提供了哈希表的实现,提高了插入和查找的效率。

示例代码

#include <iostream>
#include <unordered_set>

int main() {
    std::unordered_set<int> set = {1, 2, 3, 4, 5};

    // 插入元素
    set.insert(6);

    // 查找元素
    if (set.find(3) != set.end()) {
        std::cout << "找到了 3" << std::endl;
    }

    return 0;
}

标准库的算法更新

C++11更新了标准库中的算法,增加了新的算法和改进了现有算法的效率。例如,std::copy_if等算法提供了更强大的功能。

示例代码

#include <iostream>
#include <vector>
#include <algorithm>

int main() {
    std::vector<int> v = {1, 2, 3, 4, 5};

    // 使用 std::copy_if
    std::vector<int> even_numbers;
    std::copy_if(v.begin(), v.end(), std::back_inserter(even_numbers), [](int x) { return x % 2 == 0; });

    for (int num : even_numbers) {
        std::cout << num << " ";
    }
    std::cout << std::endl;

    return 0;
}

容器与算法的结合使用

C++11中的容器和算法结合使用可以编写高效、简洁的代码。这在处理复杂数据结构时尤其有用。

示例代码

#include <iostream>
#include <vector>
#include <algorithm>

int main() {
    std::vector<int> v = {1, 2, 3, 4, 5};

    // 使用 std::for_each
    std::for_each(v.begin(), v.end(), [](int& x) { x *= 2; });

    for (int num : v) {
        std::cout << num << " ";
    }
    std::cout << std::endl;

    // 更复杂的容器与算法结合使用
    std::vector<int> v2 = {10, 20, 30, 40, 50};

    // 分组并计数
    std::map<int, int> count;
    std::for_each(v2.begin(), v2.end(), [&count](int x) {
        count[x]++;
    });

    for (const auto& pair : count) {
        std::cout << "Value: " << pair.first << ", Count: " << pair.second << std::endl;
    }

    return 0;
}
C++11中的线程支持

基本线程操作

C++11引入了std::thread,使得线程编程更加简单和安全。

示例代码

#include <iostream>
#include <thread>

void task(int id) {
    std::cout << "Task " << id << " is running on thread " << std::this_thread::get_id() << std::endl;
}

int main() {
    std::thread t1(task, 1);
    std::thread t2(task, 2);

    t1.join();
    t2.join();

    return 0;
}

互斥锁和条件变量

C++11提供了std::mutexstd::condition_variable,用于线程间的同步。

示例代码

#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>

std::mutex mtx;
std::condition_variable cv;
bool ready = false;

void worker() {
    std::unique_lock<std::mutex> lock(mtx);
    cv.wait(lock, [] { return ready; });

    std::cout << "Worker thread: " << std::this_thread::get_id() << std::endl;
}

int main() {
    std::thread t1(worker);
    std::thread t2(worker);

    std::this_thread::sleep_for(std::chrono::seconds(1));
    {
        std::lock_guard<std::mutex> lock(mtx);
        ready = true;
    }
    cv.notify_all();

    t1.join();
    t2.join();

    return 0;
}

原子操作

C++11提供了std::atomic,允许对变量进行原子操作,以避免多线程环境中的数据竞争。

示例代码

#include <iostream>
#include <thread>
#include <atomic>

std::atomic<int> counter(0);

void increment() {
    for (int i = 0; i < 10000; ++i) {
        ++counter;
    }
}

int main() {
    std::thread t1(increment);
    std::thread t2(increment);

    t1.join();
    t2.join();

    std::cout << "Final counter value: " << counter << std::endl;

    return 0;
}

线程间的数据共享

线程间的数据共享是一个常见的应用场景,可以使用互斥锁来确保线程安全。

示例代码

#include <iostream>
#include <thread>
#include <mutex>

std::mutex mtx;
int shared_data = 0;

void increment() {
    for (int i = 0; i < 10000; ++i) {
        std::lock_guard<std::mutex> lock(mtx);
        ++shared_data;
    }
}

int main() {
    std::thread t1(increment);
    std::thread t2(increment);

    t1.join();
    t2.join();

    std::cout << "Final shared_data value: " << shared_data << std::endl;

    return 0;
}

线程池的实现

线程池是一种常见的线程管理机制,可以提高程序的响应速度和资源利用率。

示例代码

#include <iostream>
#include <thread>
#include <vector>
#include <mutex>
#include <condition_variable>

std::mutex mtx;
std::condition_variable cv;
std::vector<std::thread> workers;
bool done = false;

void worker() {
    while (true) {
        std::unique_lock<std::mutex> lock(mtx);
        cv.wait(lock, [] { return done || !workers.size(); });
        if (done) {
            break;
        }

        // 执行任务
        std::cout << "Worker thread: " << std::this_thread::get_id() << " is working" << std::endl;
    }
}

int main() {
    for (int i = 0; i < 4; ++i) {
        workers.emplace_back(worker);
    }

    std::this_thread::sleep_for(std::chrono::seconds(3));
    {
        std::lock_guard<std::mutex> lock(mtx);
        done = true;
    }
    cv.notify_all();

    for (auto& worker : workers) {
        worker.join();
    }

    return 0;
}
C++11代码示例与练习

实际应用案例

C++11中的新特性可以用于各种实际应用,例如高并发程序、复杂的数据结构处理等。

示例代码

#include <iostream>
#include <vector>
#include <thread>
#include <algorithm>

void processChunk(std::vector<int>& chunk) {
    std::vector<int> sortedChunk(chunk.size());
    std::sort(chunk.begin(), chunk.end());
}

int main() {
    std::vector<int> data = {1, 3, 5, 2, 4, 6, 8, 7, 9};

    std::vector<std::vector<int>> chunks;
    int chunkSize = data.size() / 3;

    for (int i = 0; i < data.size(); i += chunkSize) {
        std::vector<int> chunk;
        chunk.reserve(chunkSize);
        std::copy_n(data.begin() + i, chunkSize, std::back_inserter(chunk));
        chunks.push_back(chunk);
    }

    std::vector<std::thread> threads;
    for (auto& chunk : chunks) {
        threads.emplace_back(processChunk, std::ref(chunk));
    }

    for (auto& thread : threads) {
        thread.join();
    }

    for (const auto& chunk : chunks) {
        for (int num : chunk) {
            std::cout << num << " ";
        }
        std::cout << std::endl;
    }

    return 0;
}

常见问题解答

Q: 如何正确使用std::unique_ptr

A: std::unique_ptr是一种独占所有权的智能指针。通常用于避免手动管理内存,例如:

#include <iostream>
#include <memory>

int main() {
    std::unique_ptr<int> ptr(new int(10));
    std::cout << *ptr << std::endl;

    // 不能复制 unique_ptr
    // std::unique_ptr<int> ptr2 = ptr;

    // 可以移动 unique_ptr
    std::unique_ptr<int> ptr2 = std::move(ptr);
    std::cout << *ptr2 << std::endl;

    return 0;
}

Q: 如何使用std::shared_ptr

A: std::shared_ptr允许多个指针共享一个对象的生命周期。当没有指针指向该对象时,对象会被自动删除。

#include <iostream>
#include <memory>

int main() {
    std::shared_ptr<int> ptr1 = std::make_shared<int>(10);
    std::shared_ptr<int> ptr2 = ptr1;

    std::cout << *ptr1 << std::endl;
    std::cout << *ptr2 << std::endl;

    return 0;
}

练习题与参考解答

练习1: 实现一个简单的线程安全计数器。

参考解答:

#include <iostream>
#include <thread>
#include <mutex>

std::mutex mtx;
int counter = 0;

void increment() {
    for (int i = 0; i < 10000; ++i) {
        std::lock_guard<std::mutex> lock(mtx);
        ++counter;
    }
}

int main() {
    std::thread t1(increment);
    std::thread t2(increment);

    t1.join();
    t2.join();

    std::cout << "Final counter value: " << counter << std::endl;

    return 0;
}

练习2: 使用std::unordered_map存储和查找数据。

参考解答:

#include <iostream>
#include <unordered_map>

int main() {
    std::unordered_map<std::string, int> map = {{"apple", 1}, {"banana", 2}, {"cherry", 3}};

    // 插入元素
    map["date"] = 4;

    // 查找元素
    if (map.find("banana") != map.end()) {
        std::cout << "找到了 banana" << std::endl;
    }

    // 删除元素
    map.erase("apple");

    return 0;
}

练习3: 实现一个简单的Lambda表达式,用于过滤和打印元素。

参考解答:

#include <iostream>
#include <vector>

int main() {
    std::vector<int> v = {1, 2, 3, 4, 5};

    auto is_even = [](int x) { return x % 2 == 0; };

    std::vector<int> even_numbers;
    std::copy_if(v.begin(), v.end(), std::back_inserter(even_numbers), is_even);

    for (int num : even_numbers) {
        std::cout << num << " ";
    }
    std::cout << std::endl;

    return 0;
}

通过这些示例和练习,你可以更好地理解和掌握C++11的新特性和语法。

点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消