我想std::string filePath使用 lambda 表达式初始化一个类成员 ( )。程序编译正常,但没有输出。这里有什么问题?
#include <iostream>
#include <string>
class MyString
{
public:
std::string filePath = [this] ()
{
return oneStr.append(" two");
}();
std::string oneStr;
};
int main()
{
MyString str;
str.oneStr = std::string(" one");
printf("%s", str.oneStr.c_str());
}
Run Code Online (Sandbox Code Playgroud)
tes*_*08s 11
我在 Linux 5.8.6 上用 clang v10.0.1 编译了你的代码。您的代码遇到了核心转储。以下是一些日志valgrind(为了避免混淆而进行了简化):
==12170== Conditional jump or move depends on uninitialised value(s)
==12170== at 0x49BEAFE: _M_check_length (basic_string.h:322)
==12170== by 0x49BEAFE: std::string::append(char const*) (basic_string.h:1238)
==12170== by 0x10944A: MyString::filePath::{lambda()#1}::operator()[abi:cxx11]() const (test.cc:9)
==12170== by 0x109390: MyString::MyString() (test.cc:7)
==12170== by 0x109270: main (test.cc:17)
Run Code Online (Sandbox Code Playgroud)
显然函数有问题append。事实上,你的问题是你oneStr在它的初始化之前使用。
根据 cppreference:
https://en.cppreference.com/w/cpp/language/constructor
列表中成员初始化器的顺序无关紧要:实际初始化顺序如下:
...
3) 然后,非静态数据成员按照类定义中的声明顺序进行初始化。
因此,在filePath被初始化之前oneStr被初始化。对 lambda 进行评估,this捕获,this->oneStr未初始化。
更改声明的顺序将修复此未定义的行为:
#include <iostream>
#include <string>
class MyString
{
public:
std::string oneStr;
std::string filePath = [this] ()
{
return oneStr.append(" two");
}();
};
int main()
{
MyString str;
str.oneStr = std::string(" one");
printf("%s", str.oneStr.c_str());
}
Run Code Online (Sandbox Code Playgroud)
但是你仍然可能没有得到预期的结果(也许 one two?)。你只会看到 one打印出来的。那是因为 oneStr 首先用 初始化"",然后附加了" two"in MyString::MyString();但最终" one"在main功能中分配了之前打印。