字符串和函数对象

时间:2018-03-15 12:35:10

标签: c++

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

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

虽然我对char变量没有任何问题。

int main()
{
    vector<Goo> goos;

    goos.push_back(Goo('#'));
    goos.push_back(Goo('%'));

    goos[0].dobedo();
    goos[1].dobedo();

    return 0;
}

输出结果为:

Dobedo: #
Dobedo: %

有什么想法吗?

2 个答案:

答案 0 :(得分:3)

您在代码中有未定义的行为而没有定义复制构造函数。默认复制构造函数按值复制所有成员。所以你的lambda对象被复制并保存对被破坏对象的引用 - _str(当调用push_back方法时必须重新分配vector时)。

定义复制构造函数并移动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;
    };
}

答案 1 :(得分:1)

您的输出清楚地显示构造函数中_str的地址与show中的地址不同。这意味着您的对象已被复制/移动。它可能会在被推送到矢量时发生。顺便说一下,当你向矢量推送/弹出其他元素时也可能发生这种情况,因为矢量不能保证元素保持在同一个存储器地址。

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