字符串和函数对象

String and function object

本文关键字:对象 函数 字符串      更新时间:2023-10-16

我遇到了这个问题,但我不确定该怎么做...

class Goo
{
    char _ch;
    string _str;
public:
    function<void(void)> dobedo;
    // Constructor 1
    Goo(string s) : _str(s)
    {   
        cout << "Constructed: [" << &_str << "]: " << _str << endl;
        dobedo = [&]()
        {
            cout << "Dobedo: [" << &_str << "]: "<< _str << endl;
        };
    }
    // Constructor 2
    Goo(char ch) : _ch(ch)
    {
        dobedo = [&]() {
            cout << "Dobedo: " << _ch << endl;
        };
    }
    void show() { cout << "Show: [" << &_str << "]: " << _str << endl; }
};

int main()
{
    string myStr1("ABCD");
    string myStr2("EFGH");
    vector<Goo> goos;
    goos.push_back(Goo(myStr1));
    goos.push_back(Goo(myStr2));
    goos[0].dobedo();
    goos[1].dobedo();
    goos[0].show();
    goos[1].show();
    return 0;
}

由于某种原因,函数对象无法打印_str,尽管能够找到内存地址:

Constructed: [00EFF80C]: ABCD
Constructed: [00EFF7B0]: EFGH
Dobedo: [00EFF80C]:
Dobedo: [00EFF7B0]:
Show: [032F2924]: ABCD
Show: [032F296C]: EFGH

不过,我对字符变量没有任何问题。

int main()
{
    vector<Goo> goos;
    goos.push_back(Goo('#'));
    goos.push_back(Goo('%'));
    goos[0].dobedo();
    goos[1].dobedo();
    return 0;
}

输出给出:

Dobedo: #
Dobedo: %

有什么想法吗?

在未定义复制构造函数的情况下,代码中存在未定义的行为。默认复制构造函数按值复制所有成员。因此,您的lambda对象被复制,并且它包含对已销毁对象的引用 - _str(当在调用方法时必须重新分配向量时push_back(。

为类定义复制构造函数和移动构造函数Goo

Goo(const Goo& g)
{
    _str = g._str;
    dobedo = [&]()
    {
        cout << "Dobedo: [" << &_str << "]: "<< _str << endl;
    };
}
Goo(Goo&& g)
{
    _str = move(g._str);
    dobedo = [&]()
    {
        cout << "Dobedo: [" << &_str << "]: "<< _str << endl;
    };
}

您的输出清楚地表明构造函数中 _str 的地址与 show 中的地址不同。这意味着您的对象已被复制/移动。它可能在被推送到向量时发生。顺便说一句,当您将其他元素推送/弹出向量时,它也可能发生,因为向量不能保证元素保持在同一内存地址。

创建dobedo函子时,所有捕获的字段都将复制到其中。在第一种情况下,当对象被复制/移动时,_str的地址变得无效(没有人在移动/复制时更新它!有时我们可能会在该地址找到类似空字符串的东西(尽管现在访问它是内存违规(。在第二种情况下,字符被捕获并存储 - 并且在任何对象位置更改时它肯定保持有效。