c++在据称不应该有好处的地方 move 语义

标签 c++ c++11 move

我今天需要使用一些遵循这个基本设计的类:

class Task {
public:
    Task() {
        Handler::instance().add(this);
    }
    virtual void doSomething() = 0;
};

class Handler {
    std::vector<Task*> vec;
    //yea yea, we are locking the option to use default constructor etc
public:
    static Handler& instance() {
        static Handler handler;
        return handler;
    }

    void add(Task* task) {
        vec.push_back(task);
    }

    void handle() {
        for (auto t : vec) {
            t->doSomething();
        }
    }
};

template <class T, int SIZE>
class MyTask : public Task {
     T data[SIZE];
public:
    virtual void doSomething() {
        // actually do something
    }
};
//somewhere in the code:
Handler::instance().handle();

现在,我的类(class)是这样的

class A {
    MyTask<bool, 128> myTask;
public:
    A(int i) {}
};

我想做的是有一个 map ,其中 A 的实例是值

 static std::map<int, A> map = {
     {42, A(1948)},
     {88, A(-17)}
 };

首先要澄清一些事情——这段代码需要在实时嵌入式系统上运行,所以出于几个遗留原因,我不允许使用 new 分配内存。

我的问题是 map 中的实际对象不是我明确创建的对象,因此它们没有在 Handler 类中注册(所以我没有得到 Handler::handle 调用的好处)。

我试着想出一个很好的方法来解决这个问题,而不是做一些丑陋的事情,比如首先创建一个 A 数组,然后只指向 map 中的这些对象。

我以前从未使用过 move 语义,但我读过一些关于它们的内容,并认为它们可以成为我的解决方案。

然而,看了之后this answer (特别是第一个示例)似乎我无法从使用 move 语义中真正受益。

无论如何我都试过了(因为为什么不……)并做了这样的事情:

 static std::map<int, A> map = {
     {42, std::move(A(1948))},
     {88, std::move(A(-17))}
 };

令我惊讶的是,现在 MyTask 的复制构造函数仍然被调用(我将 print 放入其中进行验证)但出于某种原因现在处理程序注册工作正常并且我的实例享受 doSomething() 调用。

我尝试更深入地阅读 std::move 以了解那里到底发生了什么,但找不到答案。

谁能解释一下? std::move 是否以某种方式 move 了 this 指针?或者它可能只是导致注册以某种方式正确发生并且与 move 尝试无关真实

谢谢

编辑:

进一步澄清我的问题:

我知道 std::move 的使用对那里所做的事情没有贡献。

但出于某种原因,它确实让我的对象在 map 中通过处理程序获得 doSomething() 调用。我正在寻找这个原因

旁注,因为它可能属于不同的问题 - 是否有任何合适的方法以这种方式初始化 map 而无需两次创建每个对象的开销?

最佳答案

你的问题比它需要的要多得多,但我想我理解这里的根本问题。 std::map 构造函数接收一个 initialization_list,您正在调用 (5) from this list .遍历 initializer_list 时,对象会从 initializer_list 中复制出来,而不是 move ,因为 initializer_list 的拷贝不会复制底层对象。其他std 容器也是如此,这里用vector 的例子来演示。 (live link)

#include <vector>
#include <iostream>

struct Printer {
    Printer() { std::cout << "default ctor\n"; }
    Printer(const Printer&) { std::cout << "copy\n"; }
    Printer(Printer&&) { std::cout << "move\n"; }
};

int main() {
    std::vector<Printer> v = {Printer{}};
}

如果您使用 {std::move(Printer{})},您将在混合中添加另一个编译器无法轻易优化掉的 move 。

关于c++在据称不应该有好处的地方 move 语义,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40919319/

相关文章:

c++ - 在共享缓冲区内存中创建一个::std::string 对象

c++ - 在表达式中使用用户定义的文字有时需要空格

c++ - 包含引用另一个 vector 内容的 vector 的对象

namespaces - 将页面 move 到新的命名空间

c++ - 无法在 Visual Studio 中打开源文件 "SDKDDKVer.h"

c++ - 使用 std::string 和 char* 的最烦人的解析实例

c++ - 如何使用 boost::filesystem "normalize"路径名?

css 更改大小会通过 move 其余的 div 来影响

c++ - 将对象 move 到 malloc 的内存中是否有效 C++?

c++ - 将数据从循环存储到数组