#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <vector>
class MyClass {
public:
MyClass(int num_conds) : conds_(num_conds), mutexes_(num_conds) {
}
private:
std::vector<std::condition_variable> conds_;
std::vector<std::mutex> mutexes_;
};
int main() {
int num_conds = 5;
MyClass my_class(num_conds);
return 0;
}
我的目的是想在类初始化时根据传入的参数设置条件变量容器 cons_和互斥锁容器 mutexes_的大小,并向其中添加对应数量的元素。但是 c++的条件变量不支持拷贝复制,所以不能 push_back 。 这是 newbing 给的一段代码,能编译能跑,请问对吗?
1
crissx 2023-10-12 17:13:40 +08:00
GPT4 这样说的:
你的目标是在类初始化时根据传入的参数设置 conds_和 mutexes_的大小。目前的代码确实做到了这一点。 但你提到了关于 std::condition_variable 不支持拷贝构造的问题,这确实是一个问题。然而,你的当前代码不会触发这个问题,因为你在初始化列表中使用了构造函数直接设置了其大小,而没有使用 push_back 。 具体来说,这里: MyClass(int num_conds) : conds_(num_conds), mutexes_(num_conds) { } 你用的是 std::vector 的"fill constructor",它会创建指定数量的默认初始化的元素。在这种情况下,不涉及拷贝或移动。 总结,你的代码是可以编译和运行的,并且它按预期工作。不过,你确实要注意不要试图拷贝 std::condition_variable ,因为它确实不支持拷贝操作。如果需要移动这些对象,那么你可以考虑使用 std::vector<std::unique_ptr<std::condition_variable>>这样的结构,但在当前的代码和需求下,你不需要这么做。 |
2
sheyueji 2023-10-12 17:29:32 +08:00
push_back()除了支持拷贝构造外,还支持传递右值引用,就像楼上说的,你可以传递智能指针向 std::vector<std::unique_ptr<std::condition_variable>>中添加元素
|
3
sbldehanhan OP @crissx #1 牛啊。说的好详细啊。
|
4
sbldehanhan OP @sheyueji #2 那我也需要有条件变量的实例。我就是要在初始化时根据参数指定的数量创建条件变量的个数。
|
5
cnbatch 2023-10-12 17:44:08 +08:00
除了 push_back ,还有 emplace_back 吧
如果以后需要动态添加的话,就 emplace_back |
6
sheyueji 2023-10-12 17:44:50 +08:00
@sbldehanhan 没理解你什么意思,你在构造函数里创建对应数量的实例不就行了
|
7
ysc3839 2023-10-12 17:55:38 +08:00 via Android
看上去没问题,不支持拷贝的对象在 vector 中也可以构造时一次性初始化。
|
8
sheyueji 2023-10-12 18:04:46 +08:00
@sbldehanhan 好像是我想歪了,构造确实没问题,就是没办法再加数据了而已
|
9
cnbatch 2023-10-12 23:08:39 +08:00
@cnbatch 想起来了,不能 emplace_back ,不能直接追加。
我以前遇到过类似的,std::vector<std::atomic<T>>,一样的情况。 最后两个解决办法,第一个就是像这里提到的加一层智能指针,第二个办法比较特殊——std::map 的第二个值,不用 insert(),而是中括号直接插入。 还有我自己使用过的、改造过的第三方库就有这样的用法,构造时直接初始化。太久没碰都差不多忘了有这回事。 |
10
hitmanx 2023-10-12 23:16:19 +08:00
一般像 condition_variable 之类的,如果一定要放在 vector 里的话,用 std::unique_ptr 包一层是更好的,也更常见。
优点一是 condition_variable 本身是不支持移动的,所以你的 vector 是没法 grow 的。且用 unique_ptr 包一层,无论是将来移除个别元素还是替换都会更灵活一些。 用裸的 std::vector<std::condition_variable>主要是可以利用内存的局部性原理,因为所有的元素是放在一个 array 里的。另外相比用 unique_ptr 包一层,也可以减少一些 heap 碎片。但是在这里,似乎灵活性比这两点会更重要一些。 |
11
hitmanx 2023-10-12 23:22:37 +08:00
@cnbatch 应该不能 emplace_back 。condition_variable 是不支持 copy 且不支持 move 的。
emplace_back 会增加 vector 的 size ,所以是有可能触发 vector 的 grow 的,但是如果里面的元素不支持 move ,它是没有办法完成 grow 的。 |
13
dangyuluo 2023-10-13 04:34:05 +08:00
代码能编译但是不代表是对的,对与错还是要看你的目的是什么。至于 condition_variable 为什么不能 copy 和 move ,需要从多线程安全和操作系统原理理解了
|
14
yolee599 2023-10-13 08:20:19 +08:00 via Android
@crissx #1 发 AI 生成的内容会被站长 ban ,这是个技术问题,请问你验证过内容正确性吗?
|
15
sbldehanhan OP @cnbatch #5 无论怎么 back ,调用的都是拷贝构造函数。条件变量把拷贝构造函数删了,也就是不允许复制。
|
16
sbldehanhan OP @cnbatch #9 那你的 vector 里面的元素数量是写死的?还是在初始化时可以根据参数设置?
|
17
sbldehanhan OP @hitmanx #10 但是我需要多个条件变量,数量也不想写死。而是能在类实例化时用参数指定。
|
18
hitmanx 2023-10-13 10:58:37 +08:00
@sbldehanhan 我回复里不是写了嘛?如果数量不确定,要支持动态的 grow ,用 std::vector<std::unique_ptr<std::condition_variable>>
|
19
sbldehanhan OP @hitmanx #18 我的意思是根据参数创建对应个数的条件变量的实例。vector 里的指针不是指向一个条件变量,而是指向参数个条件变量。
|
20
cnbatch 2023-10-13 13:33:09 +08:00
@sbldehanhan
我的办法是,std::unique_ptr<std::condition_variable[]> 这样在构造函数可以手动初始化,std::make_unique<std::condition_variable[]>(想要设置的数量) https://github.com/cnbatch/kcptube/blob/main/src/3rd_party/thread_pool.hpp |