【问题标题】:Why does boost::call_traits pass small objects like pair<char, char> by reference?为什么 boost::call_traits 通过引用传递像 pair<char, char> 这样的小对象?
【发布时间】:2012-11-04 02:06:07
【问题描述】:

我需要一种方法来决定是通过复制还是通过 const-reference 传递任意类型 T(例如,如果 T 足够小,则复制 if,否则通过 const-reference 传递)。为了避免重新发明轮子,我尝试了 Boost Call Traits。

正如预期的那样,原始类型通过值传递,而像std::string 这样的复杂类型通过引用传递。然而,微小的非原始类型也通过引用传递,例如std::pair&lt;char, char&gt;,这似乎不是最佳选择。我假设直到sizeof(void*) 的所有内容都将按值传递。

一般来说,Boost 库质量很高,所以也许我遗漏了一些东西。

这是我的测试代码:

#include <iostream>
#include <type_traits>
#include <tuple>
#include <boost/call_traits.hpp>

template <typename TYPE>
void test(const char* type_name)
{
  typedef typename boost::call_traits<TYPE>::param_type T;  
  if(std::is_reference<T>::value)        
    std::cout << type_name << " is passed by reference (sizeof=" << sizeof(TYPE) << ")\n"; 
  else 
    std::cout << type_name << " is passed by value (sizeof=" << sizeof(TYPE) << ")\n"; 
}

int main()
{
  test<short>("short");
  test<int>("int");
  test<double>("double");
  test<std::string>("std::string");
  test<long long>("long long");
  test<std::pair<int, int>>("std::pair<int, int>");
  test<std::pair<short, short>>("std::pair<short, short>");
  test<std::pair<char, char>>("std::pair<char, char>");
  test<std::tuple<char, char>>("std::tuple<char, char>");
  test<std::tuple<char, char, char, char>>("std::tuple<char, char, char, char>");
  test<std::pair<long long, long long>>("std::pair<long long, long long>");
  return 0;
}

以下是结果(Boost 1.50,g++ 4.7.2):

short is passed by value (sizeof=2)
int is passed by value (sizeof=4)
double is passed by value (sizeof=8)
std::string is passed by reference (sizeof=8)
long long is passed by value (sizeof=8)
std::pair<int, int> is passed by reference (sizeof=8)
std::pair<short, short> is passed by reference (sizeof=4)
std::pair<char, char> is passed by reference (sizeof=2)
std::tuple<char, char> is passed by reference (sizeof=2)
std::tuple<char, char, char, char> is passed by reference (sizeof=4)
std::pair<long long, long long> is passed by reference (sizeof=16)

【问题讨论】:

  • 好问题。在黑暗中严重刺伤——也许是因为 boost 不能相信非基本类型的复制构造函数将是一个简单的位复制?所以一个子指针大小的类可能有一个非常昂贵的复制操作。即使知道你的类有一个默认的复制构造函数是不够的——你还必须知道所有的内容都有默认的复制构造函数,一直到原始类型。也许其中一种新的 C++0x 类型的结构符合这个含义?
  • 好点,我没有考虑用户定义的复制构造函数或复制可能是语义的类型(例如,由另一个线程修改的 std::atomic )。但是,如果类型是 POD 并且足够小,那么按值传递它应该是安全的。不幸的是,std::is_pod&lt;std::pair&lt;char, char&gt;&gt;::value 是假的。

标签: c++ boost parameter-passing


【解决方案1】:

Call Traits 是一个通用库,必须与任何用户定义的类型一起使用。要确定按值传递任意类型是否更快,需要额外的知识,这超出了库的范围。因此,在有疑问时始终按值传递的保守方法是合理的。

虽然应该可以对其进行扩展以改进对常用 STL 类型(例如,std::pairstd::tuplestd::array)的支持,但没有通用的方法可以这样做。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-06-18
    • 2023-03-08
    • 1970-01-01
    • 2018-09-01
    • 1970-01-01
    • 2014-05-27
    • 1970-01-01
    • 2014-05-22
    相关资源
    最近更新 更多