C++ 类的模板包装函数(例如std::make_pair())是否被认为是慢的?

C++ 类的模板包装函数(例如std::make_pair())是否被认为是慢的?,c++,performance,templates,copy,c++11,C++,Performance,Templates,Copy,C++11,我使用这个例子中的 STD::MaMaGueOff[2](),因为几乎任何C++程序员都应该熟悉它,但更一般地,我对它使用的模式感到疑惑。 我突然想到,尽管我喜欢std::make_pair()的便利性,但它为每个参数创建了一个“额外”副本,因为它创建了一个对并按值返回。如果我用它来插入STL容器,这意味着实际上每个参数总共被复制了3次。。。我编写此代码片段是为了说明(以及在不损失太多便利的情况下对其进行改进的一些尝试): 我意识到这里还有一些可能被消除的副本(或者更确切地说,减少为指针/智能指

我使用这个例子中的<代码> STD::MaMaGueOff[2](),因为几乎任何C++程序员都应该熟悉它,但更一般地,我对它使用的模式感到疑惑。

我突然想到,尽管我喜欢std::make_pair()的便利性,但它为每个参数创建了一个“额外”副本,因为它创建了一个对并按值返回。如果我用它来插入STL容器,这意味着实际上每个参数总共被复制了3次。。。我编写此代码片段是为了说明(以及在不损失太多便利的情况下对其进行改进的一些尝试):

我意识到这里还有一些可能被消除的副本(或者更确切地说,减少为指针/智能指针副本),例如,在这对副本中使用*或智能指针,然后自己分配

宏的想法(需要C++11)对我来说似乎很有趣,尽管我知道很多人不喜欢宏。typedef也可以很好地工作,但是您必须为每一组模板参数创建一个单独的typedef,因此它比每次显式指定模板参数更方便,但它仍然没有包装器函数那么好

我想知道实际上有没有人因为这个原因而在实践中避免使用
make\u pair()
?C++/C++11是否提供了其他有趣的解决方案


我喜欢在构造函数周围创建一个模板化函数包装器的想法,这样我们就可以推断出模板参数,但我不想因为它而对运行时产生影响。

在我的编译器中,无论有没有优化,额外的复制构造函数都被优化掉了

[10:53pm][wlynch@orange /tmp] c++ --version
Apple clang version 3.1 (tags/Apple/clang-318.0.45) (based on LLVM 3.1svn)
Target: x86_64-apple-darwin11.3.0
Thread model: posix
[10:54pm][wlynch@orange /tmp] c++ -O0 -std=gnu++11 foo.cc -o foo
[10:54pm][wlynch@orange /tmp] ./foo
Using std::make_pair()
    Copy constructor called
    Copy constructor called
Using MAKE_PAIR()
    Copy constructor called
    Copy constructor called
Using a typedef
    Copy constructor called
    Copy constructor called
如果我添加参数
-fno elide构造函数
,那么我们会看到额外的构造函数

[10:57pm][wlynch@orange /tmp] c++ -std=gnu++11 -fno-elide-constructors foo.cc -o foo
[10:57pm][wlynch@orange /tmp] ./foo
Using std::make_pair()
    Copy constructor called
    Copy constructor called
    Copy constructor called
    Copy constructor called
Using MAKE_PAIR()
    Copy constructor called
    Copy constructor called
Using a typedef
    Copy constructor called
    Copy constructor called

C++规范在2003规范中的[Copy.Reop.15 ]中跳过复制构造函数时说:

当满足某些条件时,即使对象的复制构造函数和/或析构函数有副作用,也允许实现忽略类对象的复制构造。在这种情况下,实现将省略复制操作的源和目标视为引用同一对象的两种不同方式,并且该对象的销毁发生在两个对象在未经优化的情况下销毁的时间较晚的时候。)在以下情况下允许省略复制操作(可以结合使用以消除多个副本):

  • 在具有类返回类型的函数中的return语句中,当表达式是与函数返回类型具有相同类型的非易失性自动对象的名称时,可以通过将自动对象直接构造到函数的返回值中来省略复制操作
  • 当未绑定到引用(12.2)的临时类对象将复制到具有相同cv非限定类型的类对象时,可以通过将临时对象直接构造到省略副本的目标中来省略复制操作

我认为你忽略了C++ 11中的移动语义。我发现很多C++开发者倾向于过早地优化(我自己)。如果您使用的是性能关键型代码,那么实现这两种方法和进行速度测试都是值得的。正如下面有人指出的,不管怎样,编译器很可能会对其进行优化,不会有什么不同。如果它不是性能关键型的,请使用
make_pair
以提高可读性。@AlexKorban啊,我没听说过,但听起来很有用,所以我必须研究一下。@rob05c是的,我知道你在说什么。我花了很多时间只写C代码,所以我担心它仍然对我有一点影响;)。这可能是我稍后在文章中提到的,如果它是一个问题,但是我只是想弄清楚我过去在玩C++时,我认为理所当然的一些事情。为什么<代码> -STD= GNU+11 ?为什么不
-std=c++0x
?您使用的是哪种编译器?使用g++4.6.1时,即使使用-O3,我也会得到额外的副本(我希望它也会被优化)。@FatalError:我使用的是g++4.7.0,而使用-O3时我不会得到额外的副本。@Nawaz:gnu++11是默认标准的C++11变体。默认值通常是gnu++98。@FatalError:我在编辑中添加了它,但它是随OS X Lion发布的。
[10:53pm][wlynch@orange /tmp] c++ --version
Apple clang version 3.1 (tags/Apple/clang-318.0.45) (based on LLVM 3.1svn)
Target: x86_64-apple-darwin11.3.0
Thread model: posix
[10:54pm][wlynch@orange /tmp] c++ -O0 -std=gnu++11 foo.cc -o foo
[10:54pm][wlynch@orange /tmp] ./foo
Using std::make_pair()
    Copy constructor called
    Copy constructor called
Using MAKE_PAIR()
    Copy constructor called
    Copy constructor called
Using a typedef
    Copy constructor called
    Copy constructor called
[10:57pm][wlynch@orange /tmp] c++ -std=gnu++11 -fno-elide-constructors foo.cc -o foo
[10:57pm][wlynch@orange /tmp] ./foo
Using std::make_pair()
    Copy constructor called
    Copy constructor called
    Copy constructor called
    Copy constructor called
Using MAKE_PAIR()
    Copy constructor called
    Copy constructor called
Using a typedef
    Copy constructor called
    Copy constructor called