- 主题:现代C++中,比较大的结构体一般怎么使用容器?
比如下面这样的:
struct TradeRecord
{
int bar_id; //交易发生的行情数据的位置
int trade_count; //交易数量,负数为卖出
double trade_price; //交易价格
int total_count; //交易后总数量
double total_cost ; //交易后累积历史成本
double profit; //本次交易利润,买入时统一为0
double cash ; //本次交易后剩余现金
};
传统写法,就是用指针,vector<TradeRecord*> , 不涉及任何对象拷贝、赋值。非常简单直观。
但是现代c++不提倡直接使用指针,那该怎么使用容器呢?
要定义各种赋值拷贝函数吗? 但是依然不可避免发生对象拷贝?
这种应用场景,怎么做效率高,又符合现代c++理念?
--
FROM 223.72.44.*
你那指针总要分配内存的吧,现在放vector里就不用分配内存了,其他的地方用到的话,用指针指向vector内部即可(有悬挂指针的可能)
【 在 finlab 的大作中提到: 】
: 比如下面这样的:
: struct TradeRecord
: {
: ...................
--
FROM 221.218.208.*
运行效率、空间效率、代码开发效率。
你选择一个来优化。
如果是我,我选择优化代码开发效率。就是直接 vector<TradeRecord>
如果要优化空间效率,再使用 d-pointer 技术。
如果还要优化运行效率,我再使用 copy-on-wirte 技术,减少复制。
Qt 有个 QSharedData 很方便搞这些。
【 在 finlab 的大作中提到: 】
: 比如下面这样的:
: struct TradeRecord
: {
: ...................
--
修改:hgoldfish FROM 183.253.143.*
FROM 183.253.143.*
哪个现代c++不提倡使用指针了?顶多是提倡用智能指针吧,或者是搞个右值引用和move
【 在 finlab 的大作中提到: 】
: 比如下面这样的:
: struct TradeRecord
: {
: ...................
--
修改:jimmycmh FROM 124.126.2.*
FROM 124.126.2.*
vector里边放unique_ptr好了
--
FROM 223.160.130.*
有办法直接在vector上创建新对象吗?
外面创建的对象,放入vector的时候,总要发生一次拷贝。
另外这种很多简单字段的结构体,move语义对它也没啥用。
所以,比较的就是,栈上创建发生一次拷贝的开销大,还是堆上创建并复制指针的开销大?
【 在 Bernstein 的大作中提到: 】
: 你那指针总要分配内存的吧,现在放vector里就不用分配内存了,其他的地方用到的话,用指针指向vector内部即可(有悬挂指针的可能)
:
--
FROM 223.72.40.*
c++程序员对于性能的考虑简直到了变态的地步了。而且各种教条主义盛行。
如果不是计算密集程序,怎么方便怎么用。
计算密集程序,用什么vector啊。
【 在 finlab 的大作中提到: 】
: 有办法直接在vector上创建新对象吗?
:
: 外面创建的对象,放入vector的时候,总要发生一次拷贝。
: ...................
--来自微微水木3.5.14
--
FROM 183.193.48.*
我原来的方案就是直接用二维数组(double[size][7])放全部数据,结构体都没用
一行就是一个记录,应该没有比这个开销最小了。
这不是想在不太影响性能的情况下,让程序更“现代”些。
我没怎么用过C++ 11及以后的C++,所以来请大牛们指导。
【 在 foliver 的大作中提到: 】
: c++程序员对于性能的考虑简直到了变态的地步了。而且各种教条主义盛行。
: 如果不是计算密集程序,怎么方便怎么用。
: 计算密集程序,用什么vector啊。
: ...................
--
FROM 223.72.40.*
现在C++主推模板元编程,就是见不得指针啊
用指针了,拷贝移动就都不用了,省事很多。
C++委员会该做的,是怎么提高堆内存管理的效率,再提供个可选的gc, 而不是全部用值语义来避免指针。
值语义虽然避免了指针的问题,但是处理复制需要很多额外的维护工作。
对于数量不多的大对象是可以的。 但是对于需要定义很多结构体的应用,就不太友好。
【 在 jimmycmh 的大作中提到: 】
: 哪个现代c++不提倡使用指针了?顶多是提倡用智能指针吧,或者是搞个右值引用和move
:
--
FROM 223.72.40.*
gpt4推荐直接使用值
在现代 C++ 中,确实鼓励避免直接使用裸指针,主要是为了提高代码的安全性和可维护性。对于您提到的 `TradeRecord` 结构,可以使用智能指针(如 `std::unique_ptr` 或 `std::shared_ptr`)来管理动态分配的对象,或者直接使用值语义(即直接存储对象本身,而不是指针)。
### 使用智能指针
如果您想避免对象的复制,同时保持动态分配的灵活性,可以使用 `std::unique_ptr`:
```cpp
#include <vector>
#include <memory>
std::vector<std::unique_ptr<TradeRecord>> records;
records.push_back(std::make_unique<TradeRecord>(/* 构造参数 */));
```
这种方式利用智能指针自动管理内存,避免了内存泄漏的风险。`std::unique_ptr` 保证了对象的唯一所有权,不会发生拷贝,适用于资源只被一个所有者拥有的情况。
### 使用值语义
在许多情况下,直接在容器中存储对象是可行且高效的。现代 C++ 编译器通常会很好地优化这种情况,尤其是当对象不是特别大或复杂时。例如:
```cpp
#include <vector>
std::vector<TradeRecord> records;
records.push_back(TradeRecord{/* 构造参数 */});
```
对于简单的 POD(Plain Old Data)类型,如您的 `TradeRecord` 结构体,直接使用值语义通常是非常高效的。编译器可以使用移动语义来减少不必要的拷贝。如果结构体较大或包含复杂的成员(如字符串或其他容器),则应该确保它正确地实现了移动构造函数和移动赋值操作符,这样可以避免不必要的拷贝。
### 需要赋值拷贝函数吗?
对于简单的结构体,如 `TradeRecord`,通常不需要自定义赋值拷贝函数。编译器会自动生成默认的拷贝构造函数和拷贝赋值操作符。只有当对象包含手动管理的资源(如裸指针)时,才需要考虑自定义这些函数。
### 总结
在现代 C++ 中,选择使用智能指针还是直接值存储取决于具体的应用场景和性能要求。对于简单结构体,直接在容器中存储对象是一种高效且安全的做法,编译器的优化通常足以满足性能需求。对于需要避免复制的场景,智能指针(尤其是 `std::unique_ptr`)提供了一种安全且灵活的解决方案。
【 在 finlab 的大作中提到: 】
: 比如下面这样的:
: struct TradeRecord
: {
: ...................
--
FROM 114.249.28.*