Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/jpa/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 在c+;中使用getter返回映射+;性能问题_C++_Std_Stdmap_Rvo - Fatal编程技术网

C++ 在c+;中使用getter返回映射+;性能问题

C++ 在c+;中使用getter返回映射+;性能问题,c++,std,stdmap,rvo,C++,Std,Stdmap,Rvo,我有一个类,它有3-4个类型为std::map的数据成员,用于缓存数据。它的实例被创建一次,并且数据从服务调用填充到所有映射中。我有用于访问这些映射的getter函数。(其中还包含一些线程锁定逻辑) 这些getter函数被调用了很多次,我担心性能,因为映射对象被复制了很多次 class A { private: map<string, vector<string>> m1; map<string, vector<string>>

我有一个类,它有3-4个类型为
std::map
的数据成员,用于缓存数据。它的实例被创建一次,并且数据从服务调用填充到所有映射中。我有用于访问这些映射的getter函数。(其中还包含一些线程锁定逻辑)

这些getter函数被调用了很多次,我担心性能,因为映射对象被复制了很多次

class A {
  private:
    map<string, vector<string>> m1;
    map<string, vector<string>> m2;
    map<string, vector<string>> m3;

  public:
    map<string, vector<string>> getm1() { return m1; }
    map<string, vector<string>> getm2() { return m2; } 
    map<string, vector<string>> getm3() { return m3; }
}

class B {
   B() { }
   static A a;

   map<string, vector<string>> getm1() { return a.m1; }
   map<string, vector<string>> getm2() { return a.m2; } 
   map<string, vector<string>> getm3() { return a.m3; } 
} 
这不是一个性能问题,编译器会处理吗

在阅读了一些关于返回值优化的内容并对其有了一些了解之后,编译器可以处理一些优化。这是RVO的一部分吗

提前谢谢。

将参考(
&
)返回到
const
地图

class A
{    
    using Map_type = std::map<std::string, std::vector<std::string>>;

    Map_type m1;
    Map_type m2;
    Map_type m3;

  public:
    const auto& getm1() const { return m1; }
    const auto& getm2() const { return m2; } 
    const auto& getm3() const { return m3; }
};

如果您有内部锁定,那么您不能只返回对缓存映射的引用而不引起竞争条件。您还需要向调用者提供一种方法来锁定修改后的数据。如果你正在寻找效率,那么一个设计要考虑的是这样的:

class Cache
{
public:
    using mutex_type   = std::shared_timed_mutex;
    using reading_lock = std::shared_lock<mutex_type>;
    using writing_lock = std::unique_lock<mutex_type>;

    using map_type = std::map<std::string, std::vector<std::string>>;

    reading_lock lock_for_reading() const { return reading_lock{mtx}; }
    writing_lock lock_for_writing()       { return writing_lock{mtx}; }

    map_type const& use() const { return m; }

private:

    void update_map()
    {
        // protect every update with a writing_lock
        auto lock = lock_for_writing();

        // safely update the cached map
        m["wibble"] = {"fee", "fie", "foe", "fum"};
    }

    mutable mutex_type mtx;
    map_type   m = {{"a", {"big", "wig"}}, {"b", {"fluffy", "bunny"}}};

};

int main()
{
    Cache cache;

    { // start a scope just for using the map

        // protect every access with a reading_lock
        auto lock = cache.lock_for_reading();

        // safely use the cached map
        for(auto const& s: cache.use().at("a"))
            std::cout << s << '\n';

    } // the lock is released here

    // ... etc ...
}
类缓存
{
公众:
使用mutex\u type=std::shared\u timed\u mutex;
使用reading_lock=std::shared_lock;
使用write_lock=std::unique_lock;
使用map_type=std::map;
读取\u reading()常量{return reading\u lock{mtx};}
正在为写入()写入锁定锁定{return writing锁定{mtx};}
map_type const&use()const{return m;}
私人:
void update_map()
{
//使用写锁保护每个更新
auto lock=为写入锁定_();
//安全地更新缓存的映射
m[“wibble”]={“fee”、“fie”、“foe”、“fum”};
}
可变互斥锁(mtx);
map_type m={{“a”,“big”,“wig”},{“b”,“fluffy”,“bunny”}};
};
int main()
{
缓存;
{//仅为使用映射启动一个作用域
//使用阅读锁保护每一次访问
auto lock=cache.lock_for_reading();
//安全地使用缓存的映射
for(auto const&s:cache.use().at(“a”))

std::为什么不公开地图?或者,Getter的目的是什么?返回地图副本的原因是什么?除非客户想要使用他们自己的副本,否则如果目的是返回原始地图,您应该返回地图的引用,而不是副本。您是要返回副本,还是do你只想访问映射?@CoolGeek我只想访问映射——然后这一切就变成了一个没有意义的点。返回映射的引用。如果你真的返回了一个副本,那么一旦你开始使用该副本,就要准备好与迭代器相关的错误,就像访问原始副本一样。如果你有多线程,并且一个线程有可能当其他人使用映射时,如果您正在修改映射,则您不应授予对映射的直接访问权限。不使用引用,也不使用共享指针。@Robinson
const auto&
就可以了。@SergeyA我从来都不喜欢函数返回类型使用auto。不过,其他人在工作时使用它。这种设计不允许在读取时修改容器吗?@RobertAndrzejuk如果您按照示例中所示应用锁,则不会。在继续操作之前,
write\u lock
会将所有读卡器踢出。但它确实会让调用者承担正确锁定资源的责任。对此的改进会变得相当复杂。我有一个类似的读写锁定机制。感谢您的详细解释.非常感谢!
class A
{    
    typedef std::map<std::string, std::vector<std::string>> Map_type;

    Map_type m1;
    Map_type m2;
    Map_type m3;

  public:
    const Map_type& getm1() const { return m1; }
    const Map_type& getm2() const { return m2; } 
    const Map_type& getm3() const { return m3; }
};
class Cache
{
public:
    using mutex_type   = std::shared_timed_mutex;
    using reading_lock = std::shared_lock<mutex_type>;
    using writing_lock = std::unique_lock<mutex_type>;

    using map_type = std::map<std::string, std::vector<std::string>>;

    reading_lock lock_for_reading() const { return reading_lock{mtx}; }
    writing_lock lock_for_writing()       { return writing_lock{mtx}; }

    map_type const& use() const { return m; }

private:

    void update_map()
    {
        // protect every update with a writing_lock
        auto lock = lock_for_writing();

        // safely update the cached map
        m["wibble"] = {"fee", "fie", "foe", "fum"};
    }

    mutable mutex_type mtx;
    map_type   m = {{"a", {"big", "wig"}}, {"b", {"fluffy", "bunny"}}};

};

int main()
{
    Cache cache;

    { // start a scope just for using the map

        // protect every access with a reading_lock
        auto lock = cache.lock_for_reading();

        // safely use the cached map
        for(auto const& s: cache.use().at("a"))
            std::cout << s << '\n';

    } // the lock is released here

    // ... etc ...
}