首页 > 解决方案 > 类的容器 get() 成员函数使用 vs 复制

问题描述

我创建了一个config从 config 加载配置的类YAML。我为每种类型创建了矢量容器

// Pseudo Code
class config
{
private:
    std::vector<std::string> c_name;

public:
    config(yaml_file_path)
    {
        // Handles reading from yaml and loading data to c_name container.
        load(yaml_file_path);
    }

    std::vector<std::string> get_name()
    {
        return c_name;
    }
};

我在其他类中使用此对象来获取名称配置。

class loadConfig 
{
    config cfg(yaml_file_path);
    std::vector<std::string> name = cfg.get_name();
    // Further use of vector name like checks.
}

问题:什么会更好?(作为代码练习和执行时间和/或内存空间)

  1. get_name()在代码的各个地方使用函数。或者
  2. 像我一样在容器中复制价值?

标签: c++performanceclassc++11member-functions

解决方案


什么会更好?(作为代码练习和执行时间和/或内存空间)

get_name()每次调用时,您的函数都会复制容器。这非常昂贵,只要您不想在课堂外修改它就不需要。

我建议改为使用一个/两个重载,以便编译器可以选择您调用的(非 const/ const)对象:

// for the non-const `config` objects call
std::vector<std::string>& get_name() /* noexcept */ {
    return c_name;
}

// for the const `config` objects
const std::vector<std::string>& get_name() const /* noexcept */ {
    return c_name;
}

现在在来电者处,您可以拥有

auto& name = cfg.get_name(); // non-const ref for further modifications

或者

const auto& name = cfg.get_name(); // const-ref for read only purposes.

在这两种情况下,您都不会复制容器。


话虽如此config,对于只有一个容器作为内部存储的类,我个人最喜欢的是通过提供 beginend重载来使类可迭代:

class config 
{
    std::vector<std::string> c_name;

public:    
    auto begin() noexcept { return c_name.begin(); }
    auto cbegin() const noexcept { return c_name.cbegin(); }
    auto end() noexcept { return c_name.end(); }
    auto cend() noexcept { return c_name.cend(); }
};

这使您编写代码,例如>

config names;
for (auto& name : names) // or for (auto const& name : names)
{
    // ...do something with names
}

推荐阅读