【问题标题】:Construct object from vector using move使用移动从向量构造对象
【发布时间】:2018-01-11 02:07:14
【问题描述】:

我有这样的代码:

class MyClass {
public:
    MyClass(std::vector &vec):
        v(vec)
    {}
    MyClass(??);

private:
    std::vector v;
};

我想像这样MyClass(std::move(some_vector))构造我的班级
我怎样才能做到这一点?

我可以将 4 行更改为 v(std::move(vec)),但由于危险,这是隐藏的举动。

编辑: 示例

int main {
    std::vector<int> v = {1, 2}
    MyClass myobj(v); // this should be disallowed
    //MyClass myobj(std::move(v)) //this should be the only way
    //here v is empty
}

【问题讨论】:

    标签: c++ c++11 std move stdvector


    【解决方案1】:

    我只会按值接受 std::vector,然后在内部接受 std::move

    class MyClass {
    public:
        MyClass(std::vector vec):
            v(std::move(vec))
        {}
    
    private:
        std::vector v;
    };
    

    【讨论】:

    • 我想节省空间。我将收到的矢量将不再使用。所以我想允许通过 std::move statemant 创建我的类。
    • 你仍然可以,MyClass(std::move(my_vector)) 将使用此构造函数工作,并且不会复制
    【解决方案2】:

    仅启用移动构造函数

    class MyClass {
    public:
        MyClass(std::vector &&vec):
            v(std::move(vec))
        {}
        MyClass() = delete; //prevent default constructor if you wish
    private:
        std::vector v;
    };
    

    【讨论】:

    • 看起来不错。但是我想确保只允许MyClass(std::move(my_vector))。您的代码允许显式地清空向量 (my_vector)。如果我在 5 年内修改此代码,我将不记得向量已被移动。
    • @S.R 我不明白你的问题。
    • @S.R 它不允许空向量。它允许默认构造函数。你是这个意思吗?我添加了那个。
    • 超越这个类。您在 main() 中有一个代码。你会看到MyClass(my_vector)。您是否期望在下一行 my_vector 是空的?如果只有可能我想强制使用MyClass(std::move(my_vector))
    • @S.R - 你为什么不实际发布带有main 函数的minimal reproducible example 而不是模棱两可地描述它?我敢肯定,如果您正确地澄清自己,我们的物理学家朋友会很乐意帮助您。
    【解决方案3】:

    你可以这样做:

    struct MyClass {
        // rvalue only
        MyClass(std::vector&& vec):
            v(std::move(vec))
        {}
    
        // lvalue
        MyClass(const std::vector&) = delete;
    
    private:
        std::vector v;
    };
    

    任何调用左值版本的尝试都会失败,调用已删除的重载。

    【讨论】:

      【解决方案4】:

      这将向您展示如何创建一个类 您可以选择是否启动课程 存在和/或不存在其他参数的向量。

      #include <vector>
      #include <iostream>
      #include <string>
      #include <typeinfo>
      
      using std::cout;
      using std::endl;
      using std::string;
      using std::vector;
      using std::to_string;
      
      class Parse
      {
      private:
          string         m_str;
          vector<string> m_vec;
      public:
          // Constructor 1/4 with all defaults
          Parse(){ 
              cout << "\ncreating class with all default values\n";
              m_str = "";
              m_vec.push_back("");    
          }
      
          // Constructor 2/4 with all cases used
          Parse  (string         &tmp_str,
                  vector<string> tmp_vec):
      
                  m_str          (tmp_str),
                  m_vec          (tmp_vec)
          {
              cout << "Your vector contains " + to_string(m_str.size()) + " arguments\n";
          }
      
          // Constructor 3/4 with other contents given but not vector
          Parse  (string         &tmp_str): 
                  m_str          (tmp_str)
          {
              m_vec.push_back("");
          }
          // Constructor 4/4 with only Vector given but not other contents
          Parse  (vector<string>   tmp_vec):
                  m_vec           (tmp_vec)
          {
              m_str = "";
          }
      
          string get_str_var(){return m_str;}
      
          void classed_print_vector_strings()
          {
              for (string i : m_vec){ cout << i << " \n";}
          }
      
      };
      
      
      
      // rm ./class_vector; g++ class_vector.cpp -o class_vector -std=c++17; ./class_vector arg1 arg2 arg3
      
      int main(int argc, char *argv[])
      {
          // turn **argv to a vector
          vector<string> args(argv, argv + argc);
          // iterate from argv through argv+argc
      
          // initialize with default arguments.
          Parse tracker1;
          // initalize with all used arguments
          Parse tracker2(args[0], args);
          // initalize with only the vector
          Parse tracker3(args);
          // initalzie without the vector, but with another arg
          Parse tracker4(args[0]);
      
          cout << "\nTracker 1 ---------------------\n";
          tracker1.classed_print_vector_strings();
          cout << "\nTracker 2 ---------------------\n";
          tracker2.classed_print_vector_strings();
          cout << "\nTracker 3 ---------------------\n";
          tracker3.classed_print_vector_strings();
          cout << "\nTracker 4 ---------------------\n";
          tracker4.classed_print_vector_strings();
      
      
          return 0;
      }
      
      rm ./class_vector; g++ class_vector.cpp -o class_vector -std=c++17; ./class_vector arg1 arg2 arg3
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-01-24
        • 1970-01-01
        • 1970-01-01
        • 2019-10-08
        • 2013-01-12
        • 2016-11-05
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多