【发布时间】:2014-02-14 07:07:16
【问题描述】:
我提炼了代码,最终得到了下面的代码。插入地图时出错...
感谢标记问题的人 - 希望他是第一个回答问题的人;)。
现在说真的,我的观点是:移动是在“尽力而为”的基础上完成的,并且无法确保使用它(就像这里的天真删除一样),这会造成很多混乱。对我来说,必须提供一个从未使用过的复制构造函数体来让编译器静音是很狡猾的。
当然,可能是编译器和我的stl之间的坏戏。让生活和呼吸 C++ 标准的人们来澄清。
#include <vector>
#include <map>
#include <iostream>
using namespace std;
struct FeedDataType
{
FeedDataType() {};
FeedDataType(FeedDataType&& ) = default;
#if 0
// error: use of deleted function 'FeedDataType::FeedDataType(const FeedDataType&) - why?
FeedDataType(const FeedDataType& ) = delete;
#else
// Compiles ok but never called. But cannot mark it delete...
FeedDataType(const FeedDataType& ) { cout << "Never called!" << endl; };
#endif
};
int main ()
{
vector< FeedDataType > x;
map<int, vector< FeedDataType > > mymap;
mymap.insert( std::make_pair( 0, x ) );
}
错误:
In file included from /cs/insight_san/tools/usr/bin/../lib/gcc/x86_64-unknown-linux-gnu/4.7.2/../../../../include/c++/4.7.2/vector:63:0,
from play3.cpp:1:
/cs/insight_san/tools/usr/bin/../lib/gcc/x86_64-unknown-linux-gnu/4.7.2/../../../../include/c++/4.7.2/bits/stl_construct.h: In instantiation of 'void std::_Construct(_T1*, _Args&& ...) [with _T1 = FeedDataType; _Args = {const FeedDataType&}]':
/cs/insight_san/tools/usr/bin/../lib/gcc/x86_64-unknown-linux-gnu/4.7.2/../../../../include/c++/4.7.2/bits/stl_uninitialized.h:77:3: required from 'static _ForwardIterator std::__uninitialized_copy<_TrivialValueTypes>::__uninit_copy(_InputIterator, _InputIterator, _ForwardIterator) [with _InputIterator = __gnu_cxx::__normal_iterator<const FeedDataType*, std::vector<FeedDataType> >; _ForwardIterator = FeedDataType*; bool _TrivialValueTypes = false]'
/cs/insight_san/tools/usr/bin/../lib/gcc/x86_64-unknown-linux-gnu/4.7.2/../../../../include/c++/4.7.2/bits/stl_uninitialized.h:119:41: required from '_ForwardIterator std::uninitialized_copy(_InputIterator, _InputIterator, _ForwardIterator) [with _InputIterator = __gnu_cxx::__normal_iterator<const FeedDataType*, std::vector<FeedDataType> >; _ForwardIterator = FeedDataType*]'
/cs/insight_san/tools/usr/bin/../lib/gcc/x86_64-unknown-linux-gnu/4.7.2/../../../../include/c++/4.7.2/bits/stl_uninitialized.h:260:63: required from '_ForwardIterator std::__uninitialized_copy_a(_InputIterator, _InputIterator, _ForwardIterator, std::allocator<_Tp>&) [with _InputIterator = __gnu_cxx::__normal_iterator<const FeedDataType*, std::vector<FeedDataType> >; _ForwardIterator = FeedDataType*; _Tp = FeedDataType]'
/cs/insight_san/tools/usr/bin/../lib/gcc/x86_64-unknown-linux-gnu/4.7.2/../../../../include/c++/4.7.2/bits/stl_vector.h:310:9: required from 'std::vector<_Tp, _Alloc>::vector(const std::vector<_Tp, _Alloc>&) [with _Tp = FeedDataType; _Alloc = std::allocator<FeedDataType>; std::vector<_Tp, _Alloc> = std::vector<FeedDataType>]'
/cs/insight_san/tools/usr/bin/../lib/gcc/x86_64-unknown-linux-gnu/4.7.2/../../../../include/c++/4.7.2/bits/stl_pair.h:137:64: required from 'constexpr std::pair<_T1, _T2>::pair(_U1&&, _U2&&) [with _U1 = int; _U2 = std::vector<FeedDataType>&; <template-parameter-2-3> = void; _T1 = int; _T2 = std::vector<FeedDataType>]'
/cs/insight_san/tools/usr/bin/../lib/gcc/x86_64-unknown-linux-gnu/4.7.2/../../../../include/c++/4.7.2/bits/stl_pair.h:273:72: required from 'constexpr std::pair<typename std::__decay_and_strip<_T1>::__type, typename std::__decay_and_strip<_T2>::__type> std::make_pair(_T1&&, _T2&&) [with _T1 = int; _T2 = std::vector<FeedDataType>&; typename std::__decay_and_strip<_T2>::__type = std::vector<FeedDataType>; typename std::__decay_and_strip<_T1>::__type = int]'
play3.cpp:24:44: required from here
/cs/insight_san/tools/usr/bin/../lib/gcc/x86_64-unknown-linux-gnu/4.7.2/../../../../include/c++/4.7.2/bits/stl_construct.h:77:7: error: use of deleted function 'FeedDataType::FeedDataType(const FeedDataType&)'
play3.cpp:13:9: error: declared here
原帖:
我想澄清一下编译器错误(RedHat 上的 g++ 4.7.2)。 这是什么意思:只是想强制使用移动构造函数。
所以我写:
FeedDataType(FeedDataType&& ) = default;
FeedDataType(const FeedDataType& ) = delete;
唉,它不能编译(我会省去你完整的堆栈跟踪):
.../lib/gcc/x86_64-unknown-linux-gnu/4.7.2/../../../../include/c++/4.7.2/bits/stl_construct.h:77:7: error: use of deleted function 'FeedDataType::FeedDataType(const FeedDataType&)'
在需要copy ctor的地方并不明显,我为它写了一个主体,以便在使用时让程序核心,然后查看堆栈跟踪:
FeedDataType(FeedDataType&& ) = default;
FeedDataType(const FeedDataType& ) { cerr << "Called" << endl; assert(false); }
好吧,程序编译并运行,无需输入复制 ctor 代码。那么,如果不使用,为什么不能删除复制ctor?如何确定正在使用什么?
其他我不明白的事情:
void FeedData::add( const FeedDataType & feedDataRow )
{
// Is move used here? If not why not warn?
some_vector.push_back( std::move(feedDataRow) );
}
这显然使用了复制构造函数。如果编译器发出警告/错误提示此处未使用移动构造,那会很好吗?在大型程序中,很容易错过 const 并相信 std::move 会完成这项工作。其实应该是编译器错误——feedDataRow 是 const,从它移动构造应该是不可能的吧?
使用非常量引用似乎更好,因为在这种情况下使用了移动构造函数。还是应该按价值通过这里?
我认为第一个问题是编译器错误,但希望得到知道发生了什么的人的启发。我在想移动语义很容易,但显然需要做我的功课。寻找 Meyers 先生关于 C++11 的书籍;)。
谢谢,
阿德里安
【问题讨论】:
-
std::vector我相信按值存储元素,并在调用 push back 时在内部使用复制构造函数。现在我猜你想避免这样的副本,但我不确定这是否允许,老实说我对 c++11 的这个领域不是很熟悉。 -
不是原来的编译时堆栈跟踪(你饶了我们)指向
FeedData::add吗? -
您没有回答自己的问题吗?您正在尝试从 const 转移。这是不可能的,因此尝试复制。复制被禁用,您会收到编译错误。到目前为止,一切看起来完全合乎逻辑。问题出在哪里?
-
仅仅因为一个特定的程序运行没有进入你的复制构造函数,并不意味着你的代码没有在某个地方调用它。
-
@n.m. - 我的帖子中有两个问题。第一个,为什么编译错误,仍然存在。对于第二个,我承认,我应该在 stackoverflow 中读过一点……其他人也问同样的问题,有些人提出了新的 std::force_move() 或类似的问题。但我认为这是一个有效的担忧:假设你习惯性地将其传递为 const& 然后使用 move()。如果没有真正好的眼睛或分析,某人不会知道正在发生昂贵的副本而不是移动。一些帖子讨论了这个......开始阅读;)......
标签: c++11 move-semantics