考虑下面的三个代码块,三个字符串/联合冲突的替代解决方案。
在这些选项中,一般来说,哪种方式对于以这种方式使用联盟更有效?
我正在寻找解决原则的答案:也就是说,工会的主要目的是节省内存。
编辑:课堂作业迫使我以这种方式使用工会。它让我想到哪个是最有效的,这就是我到达这里的方式。代码块(A):
// unions with pointers to structs
struct HourlyInfo {
string firstName;
string lastName;
string title;
int hoursWorked;
double hourlyRate;
};
struct SalaryInfo {
string firstName;
string lastName;
string title;
double salary;
double bonus;
};
struct Employee {
bool isHourly;
union {
HourlyInfo *hourlyEmployee;
SalaryInfo *salaryEmployee;
}
};
代码块(B):
// applying unions to relevant and non-string data types
struct Employee {
string firstName;
string lastName;
string title;
bool isHourly;
union {
struct {
double hourlyRate;
int hoursWorked;
} hourly;
struct {
double salary;
double bonus;
} salaried;
};
};
代码块(C):
// use cstring instead of string
struct HourlyInfo {
cstring firstName[50];
cstring lastName[50];
string title[50];
int hoursWorked;
double hourlyRate;
};
struct SalaryInfo {
cstring firstName[50];
cstring lastName[50];
cstring title[50];
double salary;
double bonus;
};
struct Employee {
bool isHourly;
union {
HourlyInfo hourlyEmployee;
SalaryInfo salaryEmployee;
}
};
(注意:代码背后的想法是,任何员工都是小时工资或工资,因此这里是工会。请不要建议不涉及工会的问题的替代解决方案。我不担心解决问题具体问题,我对工会感兴趣。)
此外,指针和其他数据类型的大小似乎差异很大:
What does the C++ standard state the size of int, long type to be?
How much memory does a C++ pointer use?
这是否意味着我们在这里没有关于内存效率的一揽子声明?如果是这样,我们应该在确定最有效的方法时考虑哪些因素?
答案 0 :(得分:3)
规则#1:关注你的探查器(告诉你哪个你的程序更有效)
规则#2:关于内存分配:使用自定义分配器来隐藏复杂性
规则#3:设计数据类型以明确表达意图/目的(在这个意义上,只有B是一个选项)。当然,除非规则#1需要另一次采取(这是非常不寻常的)
我知道我“不被允许”提出替代方案:( Live on Coliru )
#include <string>
#include <boost/variant.hpp>
struct HourlyInfo {
int hoursWorked;
double hourlyRate;
};
struct SalaryInfo {
double salary;
double bonus;
};
namespace detail {
template <template <typename...> class Allocator = std::allocator>
struct basic_employee {
using string = std::basic_string<char, std::char_traits<char>, Allocator<char>>;
string firstName;
string lastName;
string title;
using RateInfo = boost::variant<HourlyInfo, SalaryInfo>;
RateInfo rates;
};
}
using Employee = detail::basic_employee<>; // or use a custom (pool?) allocator
int main()
{
Employee staff1 = {
"John", "Cage", "From accounting",
SalaryInfo { 1900.00, 120.0 }
};
Employee contractor = {
"Joe", "Duffy", "Plumbing jobs",
HourlyInfo { 3, 46.00 }
};
}
答案 1 :(得分:1)
B 可能可能使用最少的内存,但50是一个很好的数字,因为它让人怀疑。
使用A,大概是你要对两种可能性中的一种进行单独的内存分配。在内存使用方面,这几乎总会带来一些低效率,而且还有指针本身的空间,所以它输给了B.但是,在两种信息结构不同的特殊情况下,它可能会获胜。在大小上超过指针大小,超过一定比例使用较小的结构,并从凶猛的低开销内存分配器(如池分配器)中分配它们。
使用C我假设你的意思是50 char
的数组,而不是50 string
或cstring
的数组。我认为名称的平均长度加上string
的开销小于50个字符,这就是我说B击败C的基础。但是,你说的是正确的string
的开销取决于一些实现细节,所以我不能断言。此外,如果你正在处理名字都不到50个字符的人,那么C就会赢。我认为这不太可能。
当然,C更受限制,因为它不能与名称超过50个字符的人交易(如果存储字符串为nul,则为49)。
[编辑:再考虑一下,字符串的开销可能是:
一个短字符串总共48或56个字节(虽然有一个名为&#34;短字符串优化&#34;这使短字符串更好,虽然取决于细节它可能使长字符串更糟)。通过string
和内存分配的实现,C将获胜,即使没有四舍五入,它也可能在斯里兰卡获胜。
因此,值得研究如何衡量实际的内存使用情况。]