使用函数初始化 C++ 结构

Posted

技术标签:

【中文标题】使用函数初始化 C++ 结构【英文标题】:C++ struct initialization with a function 【发布时间】:2021-03-17 00:16:09 【问题描述】:

我正在处理以下情况:

Struct Data;
typedef std::shared_ptr<Data> DataPtr;
typedef std::unordered_map<int, DataPtr> DataPtrMap;

DataPtrMap data;
std::string file_path;

我需要创建一个空的DataPtrMap 并使用将文件路径作为输入的函数从文件初始化它。本质上,此函数逐行读取文件,创建一个新的struct,用数据填充它并将其插入unordered_mapData 结构只包含一些整数和几个小矩阵,unordered_map 中最多可以有几千个。我想知道将指向(最初为空的)数据的指针作为函数的输入传递是否更有效:

void loadData(DataPtrMap*, const std::string&);
loadData(&data, file_path);

或者最好直接从函数中返回:

DataPtrMap loadData(const std::string&);
data = loadData(file_path);

我的直觉是,第二种解决方案在可读性方面要干净得多,返回值优化应该避免在从函数返回时制作无用的数据副本。不过,我想听听更多专业编码人员的意见。

提前感谢您的帮助。

【问题讨论】:

始终编写代码以优先考虑可读性。当您不得不返回并修复几年前代码中的错误时,过早的优化只会让您的生活更加艰难。作为一般规则,尝试始终使用最优化的“Big O”来完成这项工作,但不要担心函数调用的传递和返回性能:你的编译器总是能够做得更好比你,如果在 -O3 上那些没有得到相同的机器代码,我会感到惊讶。 为什么要共享指针? 从最愚蠢、最简单的方法开始,A) 有效,B) 有合理的机会满足性能要求。如果它满足要求,你就完成了。继续下一个问题或回家放松。如果没有,请在分析器中运行程序,看看你大部分时间都在吃什么。不要在小事上浪费时间。专注于您可以证明正在使用您绝对不必使用的时间并且值得付出努力的部分。 如果程序将 90% 的时间花在了您无法找到任何加速方法的事情上,那么您对程序所做的任何其他更改都不会引起注意。 只是补充一个观点,我从事 perf 敏感代码,1000 次削减的死亡原则是真实的。也就是说,诸如额外的小数据副本之类的东西可能永远不会出现在个人资料上,但总的来说会大大减慢程序的速度。我们的团队发现,在编写新代码时注意这些事情比以后再修复要高效得多。 【参考方案1】:

为避免在您的情况下使用原始指针,您可以在 option1 中使用引用:

void loadData(DataPtrMap&, const std::string&);
loadData(data, file_path);

使用引用,第一个选项是干净的,不需要更多优化以避免不必要的复制。

我喜欢 option2 的语法,但您需要注意优化副本。但是就像jfh说的,优化是编码的最后一步,不要一开始就在意这个

【讨论】:

嗨@leJon,我没有去参考,因为一般来说,当您阅读代码时,函数实际上修改数据似乎不太清楚。但是,在函数名称不言自明的这种特殊情况下,它可能是一种选择。谢谢你的回答。 是的,出于同样的原因,我不喜欢引用。当我分发数据的可变副本时,我更愿意在呼叫站点知道。

以上是关于使用函数初始化 C++ 结构的主要内容,如果未能解决你的问题,请参考以下文章

C++ struct结构体初始化

在 C++ 中的类构造函数中初始化结构数组

未初始化的 C++ 结构的行为

结构体的初始化(构造函数)

C 编程语言等效于 C++ 中的结构初始化

C++ STL容器+结构体+一些常用函数(持续更新)