C++作为一门兼具底层操作能力和高层抽象能力的编程语言,其语法特性和设计模式的结合使用是提升代码质量的关键。不少开发者在实际开发中会碰到语法细节混淆、设计模式适配场景不清的问题,下面结合常见疑问逐一解答。

C++语法相关常见实践问题
1. 智能指针应该优先选择shared_ptr还是unique_ptr
优先使用unique_ptr,只有当需要多个对象共享同一份资源所有权时才使用shared_ptr。unique_ptr的所有权唯一,开销更小,也不会出现循环引用的问题。shared_ptr会维护引用计数,有额外的内存和性能开销,还可能引发循环引用导致内存泄漏。
以下是两种智能指针的使用示例:
#include <memory>
#include <iostream>
class Resource {
public:
Resource() { std::cout << "Resource created" << std::endl; }
~Resource() { std::cout << "Resource destroyed" << std::endl; }
void use() { std::cout << "Using resource" << std::endl; }
};
int main() {
// unique_ptr使用示例,所有权唯一
std::unique_ptr<Resource> uniqueRes = std::make_unique<Resource>();
uniqueRes->use();
// 转移所有权,原指针失效
std::unique_ptr<Resource> anotherUnique = std::move(uniqueRes);
if (!uniqueRes) {
std::cout << "uniqueRes is null after move" << std::endl;
}
anotherUnique->use();
// shared_ptr使用示例,共享所有权
std::shared_ptr<Resource> sharedRes1 = std::make_shared<Resource>();
{
std::shared_ptr<Resource> sharedRes2 = sharedRes1;
std::cout << "sharedRes1 ref count: " << sharedRes1.use_count() << std::endl;
}
std::cout << "sharedRes1 ref count after scope: " << sharedRes1.use_count() << std::endl;
sharedRes1->use();
return 0;
}
2. 什么时候应该使用const关键字修饰成员函数
当成员函数不会修改对象的任何非静态成员变量时,就应该用const修饰。这样const对象也可以调用该成员函数,同时能明确函数的语义,避免意外修改对象状态,提升代码可读性。
示例代码如下:
#include <iostream>
#include <string>
class User {
private:
std::string name;
int age;
public:
User(std::string n, int a) : name(n), age(a) {}
// const成员函数,不修改对象状态
std::string getName() const {
return name;
}
// 非const成员函数,会修改对象状态
void setAge(int a) {
age = a;
}
int getAge() const {
return age;
}
};
int main() {
const User user("Tom", 20);
// const对象可以调用const成员函数
std::cout << "Name: " << user.getName() << std::endl;
std::cout << "Age: " << user.getAge() << std::endl;
// 以下代码会编译报错,const对象不能调用非const成员函数
// user.setAge(21);
return 0;
}
设计模式相关常见实践问题
1. 单例模式的C++实现有哪些注意事项
C++实现单例模式需要注意线程安全、防止拷贝和赋值、确保全局唯一实例。推荐使用局部静态变量实现,C++11之后局部静态变量的初始化是线程安全的,不需要额外加锁,同时要把拷贝构造函数和赋值运算符声明为删除状态,避免外部拷贝实例。
线程安全单例模式实现示例:
#include <iostream>
class Singleton {
private:
// 私有构造函数,防止外部实例化
Singleton() { std::cout << "Singleton instance created" << std::endl; }
// 删除拷贝构造函数和赋值运算符
Singleton(const Singleton&) = delete;
Singleton& operator=(const Singleton&) = delete;
public:
// 获取唯一实例的静态方法
static Singleton& getInstance() {
static Singleton instance; // 局部静态变量,C++11后线程安全
return instance;
}
void doSomething() {
std::cout << "Singleton do something" << std::endl;
}
};
int main() {
Singleton::getInstance().doSomething();
// 以下代码会编译报错,无法拷贝单例对象
// Singleton s = Singleton::getInstance();
return 0;
}
2. 工厂模式适合解决什么场景的问题
工厂模式适合需要创建大量同类型但具体实现不同的对象的场景,比如需要根据不同条件创建不同的派生类对象。它可以把对象的创建逻辑封装起来,让调用方不需要关心具体对象的创建细节,降低代码耦合度,后续新增对象类型时只需要修改工厂类,不需要修改调用方代码。
简单工厂模式示例:
#include <iostream>
#include <memory>
#include <string>
// 抽象产品类
class Product {
public:
virtual void use() = 0;
virtual ~Product() = default;
};
// 具体产品A
class ProductA : public Product {
public:
void use() override {
std::cout << "Using Product A" << std::endl;
}
};
// 具体产品B
class ProductB : public Product {
public:
void use() override {
std::cout << "Using Product B" << std::endl;
}
};
// 工厂类
class ProductFactory {
public:
static std::unique_ptr<Product> createProduct(const std::string& type) {
if (type == "A") {
return std::make_unique<ProductA>();
} else if (type == "B") {
return std::make_unique<ProductB>();
}
return nullptr;
}
};
int main() {
auto product1 = ProductFactory::createProduct("A");
if (product1) {
product1->use();
}
auto product2 = ProductFactory::createProduct("B");
if (product2) {
product2->use();
}
return 0;
}
语法和设计模式结合的实践建议
在使用设计模式时,要充分利用C++的语法特性简化实现。比如用智能指针管理设计模式中创建的对象,避免手动释放内存导致泄漏;用override关键字明确派生类重写基类虚函数,避免函数签名不一致导致的隐藏问题;用模板特性可以实现更通用的工厂模式,减少重复代码。
结合模板的通用工厂模式示例:
#include <iostream>
#include <memory>
#include <unordered_map>
#include <string>
#include <functional>
// 抽象产品类
class Product {
public:
virtual void use() = 0;
virtual ~Product() = default;
};
// 具体产品A
class ProductA : public Product {
public:
void use() override {
std::cout << "Using Product A" << std::endl;
}
};
// 具体产品B
class ProductB : public Product {
public:
void use() override {
std::cout << "Using Product B" << std::endl;
}
};
// 模板通用工厂类
template <typename T>
class GenericFactory {
private:
std::unordered_map<std::string, std::function<std::unique_ptr<T>()>> creators;
public:
void registerProduct(const std::string& type, std::function<std::unique_ptr<T>()> creator) {
creators[type] = creator;
}
std::unique_ptr<T> createProduct(const std::string& type) {
auto it = creators.find(type);
if (it != creators.end()) {
return it->second();
}
return nullptr;
}
};
int main() {
GenericFactory<Product> factory;
// 注册产品
factory.registerProduct("A", []() { return std::make_unique<ProductA>(); });
factory.registerProduct("B", []() { return std::make_unique<ProductB>(); });
// 创建产品
auto product1 = factory.createProduct("A");
if (product1) {
product1->use();
}
auto product2 = factory.createProduct("B");
if (product2) {
product2->use();
}
return 0;
}
掌握C++语法特性和设计模式的结合使用,需要多在实际项目中实践,根据场景选择合适的语法特性和设计模式,避免过度设计,才能让代码既规范又高效。