2025-05-30 06:13:38
理解 C++ 中的左值、右值及其引用形式,是掌握现代 C++(尤其是 C++11 以后的移动语义/move和完美转发/perfect forwarding)必不可少的基础。
左值指的是有名字、可寻址的对象,通常可以出现在赋值语句的左侧。
int x = 10; x = 20; // x 是左值 int* p = &x; // 可以取地址
右值是临时对象,不能被取地址,通常是表达式的结果或字面值常量。
int x = 10; int y = x + 5; // x + 5 是右值 y = 100; // 100 是右值
右值不能出现在赋值语句左侧,且生命周期通常较短。
C++ 11 引入了右值引用(通过 &&
语法),允许我们“捕获”右值。这为移动语义提供了基础。
void process(int& x); // 左值引用 void process(int&& x); // 右值引用 int main() { int a = 42; process(a); // 调用 int& process(10); // 调用 int&& }
右值引用通常与移动构造函数、移动赋值运算符、std::move
和完美转发/forwarding一起使用。
特性 | 左值(lvalue) | 右值(rvalue) |
---|---|---|
是否有名称 | 有 | 通常没有 |
是否可取地址 | 可以 | 不可以 |
是否可出现在赋值语句左侧 | 可以 | 不可以 |
生命周期 | 受作用域控制 | 通常是临时的 |
是否可绑定到 &&
|
否 | 是 |
std::string a = "hello"; std::string b = std::move(a); // a 被“移”给了 b
std::move
并不移动对象,它只是把左值强制转换为右值,从而触发移动构造函数或移动赋值运算符。
&
):
&&
):
左值和右值是 C++ 表达式语义的核心。右值引用是现代 C++ 的重要特性,能显著提高资源管理和性能表现。理解它们的区别和用法,是成为高阶 C++ 程序员的基础。
英文:C++ Lvalue, Rvalue and Rvalue References
本文一共 541 个汉字, 你数一下对不对.2025-05-29 05:37:04
assert
与 static_assert
的区别C++ 提供了两种机制来验证程序中的假设(断言):assert
和 static_assert
。虽然它们看起来类似,但它们在不同的阶段工作,并且用途也不同。
assert
用于在程序运行时验证条件是否成立。如果条件为假,程序会打印错误信息并中止运行。
#include <cassert> int divide(int x, int y) { assert(y != 0); // 如果 y 为 0,程序会中止 return x / y; }
assert
通常只在调试模式下启用,如果定义了 NDEBUG
,这些断言会被禁用。
static_assert
在编译期间检查条件是否成立。如果条件不满足,编译器会直接报错,阻止程序编译。
static_assert(sizeof(int) == 4, "此代码假设 int 是 4 字节");
它要求条件是一个常量表达式,特别适合在模板、类型检查或平台限制中使用。
特性 | assert |
static_assert |
---|---|---|
检查时机 | 运行时 | 编译时 |
是否可被禁用 | 可以(通过 NDEBUG ) |
不可以 |
是否需要常量表达式 | 不需要 | 需要 |
失败时表现 | 程序中止 | 编译失败 |
主要用途 | 调试时的逻辑检查 | 编译时的类型或平台验证 |
assert
的场景:
static_assert
的场景:
assert
和 static_assert
都能帮助你更早地发现程序中的问题,但它们发生的时间点不同。static_assert
更适合在编译阶段做静态验证,而 assert
更适合在调试阶段检查运行时逻辑。
英文:C++ assert vs static_assert
本文一共 479 个汉字, 你数一下对不对.2025-05-28 03:03:01
auto_ptr
在 C++ 中被弃用TLDR; 很久之前看到auto_ptr就觉得挺好,和auto一样,反正不用自己管,C++会自动推导智能指针的类型。不过这个关键字已经在C++ 11中被弃用/deprecated。
std::auto_ptr
在 C++ 11 中被弃用。auto_ptr
被弃用?auto_ptr
会转移所有权,并将原指针设为 nullptr
。<code>std::auto_ptr<int> p1(new int(42)); std::auto_ptr<int> p2 = p1; // 所有权被转移 std::cout << *p2 << std::endl; // 正常 std::cout << *p1 << std::endl; // 未定义行为(p1 变成 nullptr) </code>
std::unique_ptr
—— 独占所有权std::shared_ptr
—— 共享所有权<code>#include <memory> #include <iostream> int main() { std::unique_ptr<int> p1(new int(42)); std::unique_ptr<int> p2 = std::move(p1); // 转移所有权 std::cout << *p2 << std::endl; } </code>
特性 | std::auto_ptr |
std::unique_ptr |
---|---|---|
可拷贝性 | 是(但不安全) | 否 |
移动语义 | 否 | 是 |
引入/移除 | C++98 / C++17 中移除 | C++11 引入 |
在现代 C++ 中,使用 std::unique_ptr
或 std::shared_ptr
进行内存管理。不要在新的项目中再使用 auto_ptr
。
英文:Why auto_ptr is Deprecated in C++?
本文一共 236 个汉字, 你数一下对不对.2025-05-28 02:25:31
本文详细讲诉了用脚本实现定时模拟计算机按键,用于保持系统一直在线的状态。脚本可以使用VBScript、JScript和Powershell。这三种脚本语言都是微软/Microsoft的,不过前两种已经要被淘汰了。
在 Windows 环境下,这三种脚本(PowerShell、VBScript 和 JScript)都通过 CreateObject 来调用 COM 对象 WScript.Shell,以实现模拟按键的功能。例如,可以每隔一分钟模拟按下 Scroll Lock 键一次,从而保持“在线”状态(Keep Alive)。Scroll Lock 键在某些键盘上可能不存在,其作用是切换滚动锁定状态,连续按两次不会对系统造成实际影响。
有时候,你可能想模拟按键(键盘输入),例如为了自动化一些任务,相比查找 API 并写脚本,通过重复按键可能更简单。例如,你想打开任何聊天窗口并输入 “Hello!” 100 次,可以使用 PowerShell 编写一个脚本,它先暂停几秒钟,然后模拟按键。
你可以通过在 Windows 中使用 PowerShell 脚本创建 Wscript.Shell
COM 对象来实现。
$WShell = New-Object -com "Wscript.Shell" $WShell.sendkeys("Hello!")
要重复 100 次,可以在 PowerShell 中使用 FOR 循环:
$WShell = New-Object -com "Wscript.Shell" for (($i = 0), ($j = 0); $i -lt 10; $i++) { $WShell.sendkeys("Hello!") $WShell.sendkeys("{ENTER}") }
要运行一个 PowerShell 脚本,例如 .ps1 文件,你可以在 PowerShell 提示符中输入该脚本的完整路径。PowerShell 提示符也支持逐行输入 PowerShell 语句。
基于这个方法,我们可以每隔一段时间发送 Scroll-Lock 按键,直到脚本被终止。一些键盘甚至没有 Scroll-Lock 键。这个思路是模拟按键,使你的聊天程序(如 Microsoft Teams、Slack、Discord、Google Chat、Telegram 等)认为你仍然在线,从而不会将你的状态设置为 “离开”(AFK)。
$WShell = New-Object -com "Wscript.Shell" while ($true) { $WShell.sendkeys("{SCROLLLOCK}") Start-Sleep -Milliseconds 100 $WShell.sendkeys("{SCROLLLOCK}") Start-Sleep -Seconds 120 }
Microsoft VBScript 简单又方便。以下是 VBScript 版本。你可以将脚本保存为 .vbs 文件并双击运行。或者在命令行中通过 “start.exe send-keys.vbs” 或 “cscript.exe send-keys.vbs” 运行它(假设脚本名为 send-keys.vbs)。
Dim WShell Set WShell = CreateObject("Wscript.Shell") Const ASecond = 1000 Const AMinute = 60000 While True WShell.SendKeys "{SCROLLLOCK}" WScript.Sleep ASecond WShell.SendKeys "{SCROLLLOCK}" WScript.Sleep AMinute Wend
Microsoft JScript 类似于 Javascript,也可以在 Windows 上运行。以下是 JScript 版本,你可以用和 VBS 相同的方法来运行。
// alternatively // var WShell = WScript.CreateObject("Wscript.Shell"); var WShell = new ActiveXObject("Wscript.Shell"); var ASecond = 1000; var AMinute = ASecond * 60; for (;;) { WShell.SendKeys("{SCROLLLOCK}"); WScript.Sleep(ASecond); WShell.SendKeys("{SCROLLLOCK}"); WScript.Sleep(AMinute); }
顺便提一下,JScript 不支持 const 关键字和现代 Javascript 的其他语法特性。
本文展示了如何使用 PowerShell、VBScript 或 JScript 来模拟按键。一种用途就是通过模拟 SCROLLLOCK 按键来让你的聊天软件(如 Slack、Discord、Microsoft Teams、Telegram 等)显示为 “一直在线”。此外,如果你不希望电脑在你离开键盘时进入睡眠状态(尽管可以通过设置来控制),这类脚本也会派上用场。
需要注意的是,由于安全原因,这类脚本(创建 WScript.Shell COM 对象)可能会被公司的安全策略所屏蔽。不过,你仍然可以在 PowerShell 终端中逐行输入命令来绕过限制。
本文一共 723 个汉字, 你数一下对不对.2025-05-25 03:48:30
今天和媳妇约了会,大娃跟着学校去了法国旅行,二娃参加他同学的生日派对(在剑桥Leisure Park打保龄球)。刚好有两个小时空闲时间,于是我们把车停在了Hills Road,然后找了这些网红店。
平时很经常路过Hills Road,但是都没注意到这家小店,直到朋友推荐这家面包甜点咖啡店:Maison Clément
Maison Clément 是位于英国剑桥的法式手工面包与甜点店,以其正宗的法国风味和高品质的烘焙产品而闻名。自2017年在 Hills Road 开设首家店铺以来,Maison Clément 已成为当地人和游客喜爱的“剑桥小法国” 。2019年,他们在 Newnham 的 Derby Street 开设了第二家分店,进一步拓展了其影响力 。
创始人 Clément 来自巴黎,从13岁起便对烘焙产生浓厚兴趣。他在著名的巴黎 Vandermeersch 面包店完成学徒生涯,并在世界各地的邮轮上积累经验。随后,他在布莱顿的 Real Patisserie 工作了十年,不仅提升了管理技能,还结识了未来的妻子兼商业伙伴 Monika。2010年,Clément 在法国鲁昂获得了高级烘焙师资格证书。2017年,他们一家搬到剑桥,开启了 Maison Clément 的旅程 。
网址:maisonclement.co.uk
Maison Clément 每天凌晨1点开始烘焙,确保在早上7点为顾客提供新鲜出炉的面包和酥点。他们坚持使用高质量的原材料,尽可能采用本地采购,同时也从法国进口部分食材,以保证正宗的法式风味 。
招牌产品包括:
Maison Clément 在 Google 和 TripAdvisor 上均获得了高分评价。顾客赞赏其面包和甜点的高品质,以及店内温馨的氛围。不过,也有顾客提到价格相对较高,但认为物有所值 。
店铺信息:
地址:28 Hills Road, Cambridge, CB2 1LA
电话:+44 1223 324 983
营业时间:周一至周六 7:00–18:00
地址:7 Derby Street, Cambridge, CB3 9JE
电话:+44 1223 301 460
营业时间:周二至周六 7:00–17:00,周日 7:00–15:00
无论您是想享用一杯咖啡搭配新鲜出炉的羊角面包,还是寻找正宗的法式甜点,Maison Clément 都是剑桥不可错过的美食之选。
本文一共 1140 个汉字, 你数一下对不对.2025-05-25 02:34:25
consteval
?它与 const
和 constexpr
有何不同?如果你在 C++ 中经常使用 const
和 constexpr
,可能会好奇 C++20 新引入的 consteval
关键字到底是做什么用的。下面我们来一一解析。
consteval
?consteval
用于声明一个立即函数(immediate function),也就是说,这个函数必须在编译期进行求值。与 constexpr
不同,constexpr
允许函数在编译期或运行期执行,而 consteval
强制要求只能在编译期调用。
consteval int square(int x) { return x * x; }
如果尝试使用运行时参数调用此函数,将会导致编译错误。
consteval int add(int a, int b) { return a + b; } int main() { constexpr int result = add(2, 3); // 正确,编译期求值 int x = 5; // int y = add(x, 3); // 错误:add 必须在编译期调用 }
特性 | const |
constexpr |
consteval |
---|---|---|---|
引入版本 | C++11 之前 | C++11 | C++20 |
用途 | 声明只读变量 | 允许编译期求值 | 强制编译期求值 |
可用于 | 变量 | 变量、函数、构造函数 | 函数 |
是否可在运行期执行? | 是 | 可能 | 否 |
是否强制编译期? | 否 | 可选 | 是 |
consteval
?consteval std::size_t const_strlen(const char* str) { std::size_t len = 0; while (str[len] != '\0') ++len; return len; } constexpr auto len = const_strlen("Hello"); // 正确,编译期求值
consteval
是 C++ 中用于强制编译期执行的新利器。当你觉得 constexpr
不够严格时,它是实现严格编译期逻辑的最佳选择。
C++ What is the consteval? How is it different to const and constexpr?
本文一共 371 个汉字, 你数一下对不对.