Lambda:是从 lambda 未定义行为中的函数范围捕获 const char *
Lambda: Is capture of const char * from function scope in lambda undefined behaviour
我有一个 lambda,它使用在函数范围内定义的 const char *。 lambda 在函数 returns.
之后执行
void function() {
const char * UNLOCK_RESULT = "unlockResult";
..
..
TestStep::verifyDictionary(test, [UNLOCK_RESULT](TestStep::Dictionary& dict){
return 1 == dict[UNLOCK_RESULT].toInt();
});
...
}
如果我查看 GCC 生成的程序集,会发现保存 "unlockResult" 的实际字符数组是静态分配的。但我想知道这是否由标准保证,因为理论上 const char * 是函数范围的。是 const char * 未定义行为的捕获还是标准允许的,因为围绕 C++ 处理 const char * 字符串的一些异常。
我知道我可以改变:
const char * UNLOCK_RESULT=""
to
constexpr const char * UNLOCK_RESULT=""
然后讨论就结束了,因为我什至不需要捕获它,但我对 const char * 的情况很好奇。
您正在混合 2 个概念。在函数范围内是变量 UNLOCK_RESULT
本身,因此如果您尝试使用指向变量的引用或指针,那么您将获得 UB。但是当您使用该变量的值时,它是指向静态数据的指针,您完全没问题,因为这样的指针在函数终止后不会失效。
如果您的问题是指向字符串文字的指针在函数终止后是否有效,那么是的,它是有效的并且由 C++ 标准保证具有静态持续时间:
Evaluating a string-literal results in a string literal object with
static storage duration, initialized from the given characters as
specified above. Whether all string literals are distinct (that is,
are stored in nonoverlapping objects) and whether successive
evaluations of a string-literal yield the same or a different object
is unspecified.
(重点是我的)
顺便说一句,使用全大写的常量标识符是一种老习惯,因为它们以前是在预处理器中定义的。当你有大写常量的编译时标识符时,你会遇到这个习惯试图最小化的完全相同的问题。
行为定义明确。
lambda [UNLOCK_RESULT](TestStep::Dictionary& dict){...}
按值捕获指针。所以 UNLOCK_RESULT
内部的 lambda 是原始 UNLOCK_RESULT
的 copy,后者在 lambda 的持续时间内不必存在。
现在字符串文字 "unlockResult"
有 static storage duration, which means it's allocated at program start and remains available for the duration of the program:
All variables which do not have dynamic storage duration, do not have thread storage duration, and are not local have static storage duration. The storage for these entities shall last for the duration of the program.
我有一个 lambda,它使用在函数范围内定义的 const char *。 lambda 在函数 returns.
之后执行void function() {
const char * UNLOCK_RESULT = "unlockResult";
..
..
TestStep::verifyDictionary(test, [UNLOCK_RESULT](TestStep::Dictionary& dict){
return 1 == dict[UNLOCK_RESULT].toInt();
});
...
}
如果我查看 GCC 生成的程序集,会发现保存 "unlockResult" 的实际字符数组是静态分配的。但我想知道这是否由标准保证,因为理论上 const char * 是函数范围的。是 const char * 未定义行为的捕获还是标准允许的,因为围绕 C++ 处理 const char * 字符串的一些异常。
我知道我可以改变:
const char * UNLOCK_RESULT=""
to
constexpr const char * UNLOCK_RESULT=""
然后讨论就结束了,因为我什至不需要捕获它,但我对 const char * 的情况很好奇。
您正在混合 2 个概念。在函数范围内是变量 UNLOCK_RESULT
本身,因此如果您尝试使用指向变量的引用或指针,那么您将获得 UB。但是当您使用该变量的值时,它是指向静态数据的指针,您完全没问题,因为这样的指针在函数终止后不会失效。
如果您的问题是指向字符串文字的指针在函数终止后是否有效,那么是的,它是有效的并且由 C++ 标准保证具有静态持续时间:
Evaluating a string-literal results in a string literal object with static storage duration, initialized from the given characters as specified above. Whether all string literals are distinct (that is, are stored in nonoverlapping objects) and whether successive evaluations of a string-literal yield the same or a different object is unspecified.
(重点是我的)
顺便说一句,使用全大写的常量标识符是一种老习惯,因为它们以前是在预处理器中定义的。当你有大写常量的编译时标识符时,你会遇到这个习惯试图最小化的完全相同的问题。
行为定义明确。
lambda [UNLOCK_RESULT](TestStep::Dictionary& dict){...}
按值捕获指针。所以 UNLOCK_RESULT
内部的 lambda 是原始 UNLOCK_RESULT
的 copy,后者在 lambda 的持续时间内不必存在。
现在字符串文字 "unlockResult"
有 static storage duration, which means it's allocated at program start and remains available for the duration of the program:
All variables which do not have dynamic storage duration, do not have thread storage duration, and are not local have static storage duration. The storage for these entities shall last for the duration of the program.