如何在嵌套向量中构造不可复制、不可移动的class?
How to contruct non-copyable, non-moveable class in a nested vector?
我想使用不可复制、不可移动的非默认构造函数构造一个向量 class。使用默认构造函数它工作正常,我可以构造一个向量,只要我不调整它的大小。但是不知何故,对于非默认构造函数,它似乎必须复制。有谁知道我是否可以在使用非默认构造函数的构造过程中避免复制操作,以便我可以继续使用 vector?
#include <vector>
#include <mutex>
class A {
public:
A(int num) : vec(num) {}
private:
std::vector<std::mutex> vec;
};
class B {
public:
B(int numB, int numA) : vec(numB, numA) {}
private:
std::vector<A> vec;
};
int main() {
B b(2, 3);
return 0;
}
当我尝试编译它时,我得到:
/usr/include/c++/9/bits/stl_uninitialized.h:127:72: error: static assertion failed: result type must be constructible from value type of input range
您可以直接使用 std::vector<std::mutex>
,因为使用标准库容器时的类型要求仅限于调用它们的函数所需的类型。
一旦你用一些元素构造了一个 std::vector<std::mutex>
,只有可能添加新元素或删除旧元素的操作需要值类型是可移动的。访问向量元素和移动向量本身不是问题。
用 vec(num)
构造向量是可行的,因为它只默认构造已知数量的元素。它可以在存储中就地构建新元素。
vec(numB, numA)
使用的构造函数实际上将元素的数量和对值类型对象的 const
左值引用作为参数。它不需要构造函数参数来从就地构造新元素。相反,当您传递它时 numA
,numA
被隐式转换为 A
(通过非 explicit
构造函数)并传递对该 A
的引用给构造函数。
然后指定构造函数从传递的对象复制构造向量元素。
但是因为 std::vector<std::mutex> vec;
不可复制,所以 A
也不是,所以它失败了。
但是 std::vector
的另一个构造函数可以在没有 copy/move 构造函数的情况下构造对象:采用迭代器范围的构造函数。但是,要使用它,我们首先需要构造一个迭代器范围,并将构造函数参数传递给向量元素的构造函数:
auto args = std::vector(numB, numA);
vec = {args.begin(), args.end()};
或者,使用显式类型:
std::vector<int> args(numB, numA);
vec = std::vector<A>(args.begin(), args.end());
如果您想在成员启动器列表中执行此操作,您可以将其委托给成员函数或 lambda 和 return
而不是 vec =
。
迭代器范围构造函数通过转换 *it
就地构造向量元素,如果迭代器是前向迭代器(如上例),则构造函数不需要任何移动操作。
请注意 vec.assign(args.begin(), args.end())
不起作用,因为 assign
允许使用赋值而不是构造。
我想使用不可复制、不可移动的非默认构造函数构造一个向量 class。使用默认构造函数它工作正常,我可以构造一个向量,只要我不调整它的大小。但是不知何故,对于非默认构造函数,它似乎必须复制。有谁知道我是否可以在使用非默认构造函数的构造过程中避免复制操作,以便我可以继续使用 vector?
#include <vector>
#include <mutex>
class A {
public:
A(int num) : vec(num) {}
private:
std::vector<std::mutex> vec;
};
class B {
public:
B(int numB, int numA) : vec(numB, numA) {}
private:
std::vector<A> vec;
};
int main() {
B b(2, 3);
return 0;
}
当我尝试编译它时,我得到:
/usr/include/c++/9/bits/stl_uninitialized.h:127:72: error: static assertion failed: result type must be constructible from value type of input range
您可以直接使用 std::vector<std::mutex>
,因为使用标准库容器时的类型要求仅限于调用它们的函数所需的类型。
一旦你用一些元素构造了一个 std::vector<std::mutex>
,只有可能添加新元素或删除旧元素的操作需要值类型是可移动的。访问向量元素和移动向量本身不是问题。
用 vec(num)
构造向量是可行的,因为它只默认构造已知数量的元素。它可以在存储中就地构建新元素。
vec(numB, numA)
使用的构造函数实际上将元素的数量和对值类型对象的 const
左值引用作为参数。它不需要构造函数参数来从就地构造新元素。相反,当您传递它时 numA
,numA
被隐式转换为 A
(通过非 explicit
构造函数)并传递对该 A
的引用给构造函数。
然后指定构造函数从传递的对象复制构造向量元素。
但是因为 std::vector<std::mutex> vec;
不可复制,所以 A
也不是,所以它失败了。
但是 std::vector
的另一个构造函数可以在没有 copy/move 构造函数的情况下构造对象:采用迭代器范围的构造函数。但是,要使用它,我们首先需要构造一个迭代器范围,并将构造函数参数传递给向量元素的构造函数:
auto args = std::vector(numB, numA);
vec = {args.begin(), args.end()};
或者,使用显式类型:
std::vector<int> args(numB, numA);
vec = std::vector<A>(args.begin(), args.end());
如果您想在成员启动器列表中执行此操作,您可以将其委托给成员函数或 lambda 和 return
而不是 vec =
。
迭代器范围构造函数通过转换 *it
就地构造向量元素,如果迭代器是前向迭代器(如上例),则构造函数不需要任何移动操作。
请注意 vec.assign(args.begin(), args.end())
不起作用,因为 assign
允许使用赋值而不是构造。