【虚幻引擎】UC++与标准C++的区别

Tuesday, Mar 19, 2024 | 2 minute read | Updated at Tuesday, Mar 19, 2024

@

1. 类声明与反射系统

1.1 类定义语法

Unreal C++

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
// 必须继承UObject且使用反射宏
UCLASS(Blueprintable, meta=(DisplayName="My Object"))
class UMyObject : public UObject {
    GENERATED_BODY() // 必须包含
    
    UPROPERTY(EditAnywhere, Category="Stats")
    float Health = 100.0f;

    UFUNCTION(BlueprintCallable)
    void Heal(float Amount);
};

标准 C++

1
2
3
4
5
6
7
8
class MyObject {
public:
    float Health = 100.0f;
    
    void Heal(float Amount) {
        Health += Amount;
    }
};

1.2 反射机制对比

特性Unreal C++标准 C++
运行时类型信息通过UCLASS宏自动生成仅支持有限RTTI
动态属性访问UPROPERTY字段可通过名字字符串访问需要手动实现反射系统
方法调用UFUNCTION支持蓝图调用和RPC只能静态调用

2. 内存管理模型

2.1 对象生命周期

Unreal C++

1
2
3
4
5
6
7
// 自动垃圾回收
UMyObject* Obj = NewObject<UMyObject>();
Obj->MarkPendingKill(); // 标记销毁

// 手动控制引用
Obj->AddToRoot(); // 防止被GC
Obj->RemoveFromRoot();

标准 C++

1
2
3
4
5
6
// 手动管理
MyObject* obj = new MyObject();
delete obj;

// 或使用智能指针
auto ptr = std::make_shared<MyObject>();

2.2 内存分配器对比

1
2
3
4
5
6
7
// Unreal自定义分配器
FMemory::Malloc(Size);
FMemory::Free(Ptr);

// 标准库分配器
void* p = std::malloc(size);
std::free(p);

3. 核心数据类型差异

3.1 字符串处理

Unreal C++

1
2
3
4
5
FString Str = TEXT("Hello"); // UTF-16
FText Text = NSLOCTEXT("NS", "Key", "Localized Text");

// 格式化
FString Format = FString::Printf(TEXT("%s:%d"), *Str, 42);

标准 C++

1
2
std::string str = "Hello"; // 依赖编码
std::string format = std::format("{}:{}", str, 42); // C++20

3.2 容器类对比

数组操作

1
2
3
4
5
6
7
8
9
// Unreal
TArray<int32> Arr;
Arr.Add(1);
Arr.Remove(0);

// 标准库
std::vector<int> vec;
vec.push_back(1);
vec.erase(vec.begin());

字典操作

1
2
3
4
5
6
7
// Unreal
TMap<FName, FString> Map;
Map.Add("Key", "Value");

// 标准库
std::unordered_map<std::string, std::string> map;
map.emplace("Key", "Value");

4. 多线程编程

4.1 任务系统

Unreal C++

1
2
3
4
5
6
7
8
9
// GameThread执行
AsyncTask(ENamedThreads::GameThread, [](){
    UE_LOG(LogTemp, Warning, TEXT("Main thread"));
});

// 并行任务
ParallelFor(10, [](int32 Index){
    // 并行执行
});

标准 C++

1
2
3
4
std::thread t([](){
    std::cout << "New thread" << std::endl;
});
t.join();

5. 编译系统差异

5.1 模块定义

Unreal模块

1
2
3
4
5
6
// MyModule.Build.cs
public class MyModule : ModuleRules {
    public MyModule(ReadOnlyTargetRules Target) {
        PublicDependencyModuleNames.AddRange(new string[] { "Core" });
    }
}

CMake示例

1
2
add_library(MyModule STATIC src.cpp)
target_link_libraries(MyModule PUBLIC Core)

6. 常用宏对比

6.1 常用Unreal宏

1
2
3
UE_LOG(LogTemp, Warning, TEXT("Message")); // 日志
check(ptr != nullptr); // 断言
ensureMsgf(bCondition, TEXT("Message")); // 带消息断言

6.2 标准C++等效

1
2
3
std::cout << "Message" << std::endl; // 日志
assert(ptr != nullptr); // 断言
if(!bCondition) throw std::runtime_error("Message"); // 异常

7. 最佳实践建议

  1. 在Unreal项目中
    • 始终使用UCLASS()/UFUNCTION()暴露需要反射的类
    • UObject派生类不要使用智能指针
    • 使用TArray代替std::vector以获得更好性能
  2. 在独立模块中
    • 可使用标准库容器和智能指针
    • 通过纯接口类与Unreal代码交互
    • 将标准C++代码封装在Private目录
  3. 通用规则
    • 避免在头文件中混合两种风格的代码
    • 对性能关键路径使用Unreal优化容器
    • 跨平台代码优先使用Unreal封装

© 2021 - 2026 古月月仔的博客

🌱 Powered by Hugo with theme Dream.

关于我
  • 我是古月月仔
  • Ethan Hu
  • 分享技术学习笔记与生活点滴
  • 现居: 上海 中国
  • 家乡: 平遥 山西
在用的学习工具
  • 📝 Typora —— 极致简洁的 Markdown 编辑器,助力沉浸式文档撰写与知识记录。
  • 📓 Notion —— 一站式工作空间,用于搭建个人知识库、项目管理与深度协作。
  • 🔗 N8N —— 强大的基于节点的自动化工作流工具,轻松实现不同应用间的逻辑联动。
  • 🤖 Gemini —— 智能 AI 助手,在代码辅助、创意激发与信息检索中提供强力支撑。
我的爱好
  • 🚀 喜欢折腾各种好玩的技术
  • 📸 业余摄影爱好者
  • 🎮 各类游戏玩家
  • 💻 数码产品折腾爱好者
  • 📚 阅读:赫尔曼·黑塞 & 阿尔贝·加缪
  • 🎞️ 追番中:《电锯人:蕾塞篇》
  • 🎬 经典重温:《命运石之门》
最近正在学