Inv*_*rse 22 c++ gcc mingw rvalue-reference c++11
我正在为linux和windows编写一个应用程序,并注意到GCC构建产生了许多对复制构造函数的无用调用.
以下是产生此行为的示例代码:
struct A
{
A() { std::cout << "default" << std::endl; }
A(A&& rvalue) { std::cout << "move" << std::endl; }
A(const A& lvalue) { std::cout << "copy" << std::endl; }
A& operator =(A a) { std::cout << "assign" << std::endl; return *this; }
};
BOOST_AUTO_TEST_CASE(test_copy_semantics)
{
std::vector<A> vec_a( 3 );
}
Run Code Online (Sandbox Code Playgroud)
此测试仅创建3个元素的向量.我期望3个默认构造函数调用和0个副本,因为没有A左值.
在Visual C++ 2010中,输出为:
default
move
default
move
default
move
Run Code Online (Sandbox Code Playgroud)
在GCC 4.4.0(MinGW)中,( - 02 -std = c ++ 0x),输出为:
default
copy
copy
copy
Run Code Online (Sandbox Code Playgroud)
发生了什么,我该如何解决?副本对于实际类来说是昂贵的,默认构造和移动都很便宜.
How*_*ant 18
这两种实现(Visual C++ 2010和GCC 4.4.0)都有错误.正确的输出是:
default
default
default
Run Code Online (Sandbox Code Playgroud)
这在23.3.5.1 [vector.cons]/4中规定:
要求:T应为DefaultConstructible.
不允许实现假设A是MoveConstructible或CopyConstructible.
看起来问题是你拥有的g ++版本没有C++ 0x完全兼容的库.特别是,在C++ 03中,std :: vector的size构造函数具有以下签名:
// C++ 03
explicit vector(size_type n, const T& value = T(),
const Allocator& = Allocator());
Run Code Online (Sandbox Code Playgroud)
使用该函数签名和您的调用,创建临时,然后由常量引用绑定,并为每个元素创建它的副本.
而在C++ 0x中有不同的构造函数:
// C++0x
explicit vector(size_type n);
vector(size_type n, const T& value, const Allocator& = Allocator());
Run Code Online (Sandbox Code Playgroud)
在这种情况下,您的调用将匹配第一个签名,并且元素应该默认构造,并在容器上放置new(正如@Howard Hinnant在他的回答中正确指出的,编译器根本不应该调用移动构造函数).
您可以尝试检查更新版本的g ++是否有更新的标准库,或者您可以通过手动添加元素来解决此问题:
std::vector<A> v;
v.reserve( 3 ); // avoid multiple relocations
while (v.size() < 3 ) v.push_back( A() );
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
494 次 |
| 最近记录: |