【问题标题】:C++ Static inside functionC++ 静态内部函数
【发布时间】:2017-05-15 21:47:45
【问题描述】:

您好,我有一个返回 std::pair 的函数,并且经常被调用。

std::pair<sf::Vector2i, sf::Vector2i> 
Map::map_coord_to_chunk_coord(int x, int y) {
  // Get the chunk position
  int chunk_x = x / CHUNK_SIZE;
  int chunk_y = y / CHUNK_SIZE;

  // Get the position inside the chunk
  x = x - chunk_x * CHUNK_SIZE;
  y = y - chunk_y * CHUNK_SIZE;

  // Return the chunk position and the position inside it
      return std::pair<sf::Vector2i, sf::Vector2i>(sf::Vector2i(chunk_x, 
chunk_y), sf::Vector2i(x, y));
}

将这对声明为静态是否更好,这样就不会每次都创建它。

std::pair<sf::Vector2i, sf::Vector2i> 
Map::map_coord_to_chunk_coord(int x, int y) {
  static std::pair<sf::Vector2i, sf::Vector2i> coords;

  // Get the chunk position
  coords.first.x = x / CHUNK_SIZE;
  coords.first.y = y / CHUNK_SIZE;

  // Get the position inside the chunk
  coords.second.x = x - coords.first.x * CHUNK_SIZE;
  coords.second.y = y - coords.first.y * CHUNK_SIZE;

  // Return the chunk position and the position inside it
  return coords;
}

我运行 callgrind,看起来这个函数快了 3 倍,但这是一个好习惯吗?

【问题讨论】:

  • 在什么方面更好? “良好做法”是基于意见的。
  • 这个坐标只能在这个函数中使用?我的意思是你声明了对象坐标并且只有在 map_coord_to_chunk_coord 里面才能使用它?
  • 你是如何测量速度增加的?我认为return {{(chunk_x, chunk_y}, {x, y}}; 可以正常工作
  • 是的,只有这个函数使用它,通过良好的实践,我的意思是这会产生一些问题吗?
  • @Snps 这绝对是关于整数除法,否则计算将毫无意义。

标签: c++


【解决方案1】:

一般来说,当唯一的目标是节省 CPU 周期时,应该避免使用static

使coords 静态呈现您的map_coord_to_chunk_coord 函数non-reentrant,这意味着它在没有适当同步的并发环境中不再可用。这是为了节省一个简单对象的构建成本而付出的非常高昂的代价。

例如,您应该能够通过使用make_pair 来优化std::pair 的构造:

inline std::pair<sf::Vector2i, sf::Vector2i> 
Map::map_coord_to_chunk_coord(int x, int y) {
    int first_x = x / CHUNK_SIZE;
    int first_y = y / CHUNK_SIZE;
    return std::make_pair(
        sf::Vector2i(first_x, first_y)
    ,   sf::Vector2i(x - first_x * CHUNK_SIZE, y - first_y * CHUNK_SIZE)
    );
}

在某些情况下编译器can even optimize out the copying,进一步提高性能。

【讨论】:

  • 至少它在问题中的书写方式并没有保存结构,而是添加了一个。
  • @nwp 我认为这取决于调用者是否分配给现有变量。
【解决方案2】:

正如其他人指出的那样,您通常应该避免以这种方式使用局部静态变量,因为它会使代码非线程安全。

通常,最惯用的 C++ 是依赖返回值优化和其他编译器优化。如果构造 std::pairsf::Vector2i 是您代码中的瓶颈,我会感到惊讶(并且有点羡慕),但如果这确实是您代码的关键部分,您可能会稍微不那么惯用和传递-引用而不是使用返回值:

void
map_coord_to_chunk_coord(int x, int y, std::pair<Vector2i, Vector2i>& chunk_coord) {
    chunk_coord.first.x = x / CHUNK_SIZE;
    chunk_coord.first.y = y / CHUNK_SIZE;
    chunk_coord.second.x = x % CHUNK_SIZE;
    chunk_coord.second.y = y % CHUNK_SIZE;
}

然后调用者可以在紧密循环中重复使用chunk_coord 变量,并且您没有std::pairsf::Vector2i 的构造。

【讨论】:

    【解决方案3】:

    没有。

    无论如何你都必须复制它(按值返回!),所以你一无所获。

    (实际上你添加了一个结构。)

    你所做的只是让你的函数不可重入,这是一个倒退。

    【讨论】:

      猜你喜欢
      • 2011-06-29
      • 2019-11-28
      • 1970-01-01
      • 2013-11-10
      • 1970-01-01
      • 2023-03-30
      • 1970-01-01
      • 2021-02-02
      • 2020-08-04
      相关资源
      最近更新 更多