【问题标题】:Does moving an element from an STL container remove it from that container?从 STL 容器中移动元素是否会将其从该容器中移除?
【发布时间】:2012-02-16 23:12:20
【问题描述】:

我有一个带有sayHello() 方法的Foobar 类,该方法输出“你好!”。如果我写下面的代码

vector<unique_ptr<Foobar>> fooList;
fooList.emplace_back(new Foobar());

unique_ptr<Foobar> myFoo = move(fooList[0]);
unique_ptr<Foobar> myFoo2 = move(fooList[0]);
myFoo->sayHello();
myFoo2->sayHello();

cout << "vector size: " << fooList.size() << endl;

输出是:

Well hello there!
Well hello there!
vector size: 1

我很困惑为什么会这样。当我迈出第一步时,fooList[0] 不应该变为 null 吗?为什么myFoo2 有效?

Foobar 是这样的:

class Foobar
{
public:
    Foobar(void) {};
    virtual ~Foobar(void) {};

    void sayHello() const {
        cout << "Well hello there!" << endl; 
    };
};

【问题讨论】:

    标签: c++ visual-studio-2010 stl move-semantics


    【解决方案1】:

    当我做第一步时 fooList[0] 不应该变成 null 吗?

    是的。

    为什么 myFoo2 有效?

    它没有;它会导致未定义的行为。如果您使用空指针调用不取消引用 this 的非虚拟函数,您的编译器恰好生成不会崩溃的代码。

    如果你改变函数如下,它会更清楚发生了什么:

    void sayHello() const {
        cout << "Well hello there! My address is " << this << endl; 
    }
    
    Well hello there! My address is 0x1790010
    Well hello there! My address is 0
    vector size: 1
    

    【讨论】:

    • 啊哈!这突然变得很有意义。该向量仍然显示大小 1,但它现在只是 nullptr 的一个 unique_ptr,并且当向量超出我希望的范围时将被清理。看起来一切都按我的预期工作,正如你所指出的,我的编译器只是在欺骗我。谢谢!
    • 我向Foobar 添加了一个数据成员,并在sayHello() 中访问它。现在代码崩溃了,正如我在尝试使用 myFoo2 时所期望的那样。
    【解决方案2】:

    答案是:不,移动操作不会从容器中移除元素。

    另一种说法:emplace_back 函数的使用很可能是不够的。

    尝试:

    vector<unique_ptr<Foobar>> fooList;
    fooList.emplace_back( new Foobar );
    

    【讨论】:

    • @Mike Seymour 已澄清 move() 实际上会将对象移出向量,但归零的 unique_ptr 将保留在向量中。另外,感谢您指出我的emplace_back 电话的变化。您的示例编译并运行良好,我相信它避免了额外的构造函数。
    • 我已经编辑了我的原始问题以反映您的更正,以防将来有人偶然发现代码。
    • 我想突出显示该项目将持续存在于向量中。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-07
    • 1970-01-01
    • 2017-05-05
    • 2015-01-09
    • 2016-05-29
    相关资源
    最近更新 更多