C++ 如何从字符串向量构造对象并避免复制?

C++ 如何从字符串向量构造对象并避免复制?,c++,copy-constructor,C++,Copy Constructor,假设MyClass有两个std::vector类型的成员变量,一个是Data类型的结构,另一个是StrData(包含字符串)成员变量。我删除了默认构造函数和复制构造函数,以防止编译器进行不必要的复制: struct Data { int x; float y; Data(int x, float y) : x(x), y(y) {} Data() = delete; Data(const Data& other) = delete; }; st

假设
MyClass
有两个
std::vector
类型的成员变量,一个是
Data
类型的结构,另一个是
StrData
(包含字符串)成员变量。我删除了默认构造函数和复制构造函数,以防止编译器进行不必要的复制:

struct Data {
    int x;
    float y;
    Data(int x, float y) : x(x), y(y) {}
    Data() = delete;
    Data(const Data& other) = delete;
};


struct StrData {
std::string xstr;
    StrData(std::string x) : xstr(x){}
    StrData() = delete;
    StrData(const StrData& other) = delete;
};


class MyClass {
    std::vector<Data> m_vect_data;
    std::vector<StrData> m_vect_str_data;
public:
    MyClass(const std::vector<Data> &m_vect_data,
            const std::vector<StrData> &m_vect_str_data) : m_vect_data(
            m_vect_data), m_vect_str_data(m_vect_str_data) {}
};
在编译此代码时,我收到了如下投诉:

/usr/include/c++/7/bits/stl_construct.h:75:7: error: use of deleted function ‘StrData::StrData(const StrData&)’
编译器为什么要更正初始化的结构
数据
呢
仅包含整型(int和float),而不能初始化

第二个结构,即
StrData
,不需要复制构造函数

您可以移动,而不是复制

首先,使用
向量(std::initializer_list,const分配器&)有一个问题向量的构造函数。初始值设定项列表只能复制,因此不可复制的类型不能复制

另一种方法是,首先将列表声明为数组,创建一系列移动迭代器,然后改用迭代器构造函数:

Data datas[] = {
    {1,2.0},
    {2,4.0},
};
StrData strs[] = {
    {"name"},
};
MyClass s{
    {std::make_move_iterator(std::begin(datas)), std::make_move_iterator(std::end(datas))},
    {std::make_move_iterator(std::begin(strs)), std::make_move_iterator(std::end(strs))},
};
现在,这还不起作用,因为构造函数从参数向量复制。简单的解决方案是按值获取向量,并将其移动到成员中:

MyClass(std::vector<Data> m_vect_data,
        std::vector<StrData> m_vect_str_data
       ) : m_vect_data(std::move(m_vect_data)),
           m_vect_str_data(std::move(m_vect_str_data))
       {}

附言

使类不可复制只是作为查找意外副本的调试工具。尤其是在
数据
的情况下,它的复制速度与移动速度一样快


而且,在构造函数中接受向量是非常有限的。如果您可以使用模板,您可以使用一个模板构造函数来代替迭代器对。

这可能是编译器遇到的第一个错误,此时它中止了编译构造函数的尝试,我删除了默认构造函数和复制构造函数,以防止编译器进行不必要的复制——我不太理解这种推理。如果编译器是一个好的编译器,那么它不会进行“不必要的复制”。看起来您可能正在调用“过早优化”。您有
const std::vector&m_vect_stru_data
,然后是
m_vect_stru data(m_vect_stru data
。除了复制之外,您希望如何从
const
vector
中获取数据?您可能正在寻找右值引用和移动语义。
MyClass(std::vector<Data> m_vect_data,
        std::vector<StrData> m_vect_str_data
       ) : m_vect_data(std::move(m_vect_data)),
           m_vect_str_data(std::move(m_vect_str_data))
       {}
struct Data {
    // ...
    Data(Data&&);
};
struct StrData {
    // ...
    StrData(StrData&&);
};