测试对象是否已被移动

时间:2012-11-10 23:42:07

标签: c++ c++11 move-semantics universal-reference

我正在测试我的容器包装器是否正确实现URefs。我能想到的唯一明显的方法是尝试找出一种检测物体是否被移动的方法。

是否有一种好的测试方法可以确保没有复制对象?还是有另一种方法来测试我想要的东西?我更喜欢不需要修改我正在测试的类的解决方案。因为有几十个。

  

请您提供更多关于您拥有的信息?就像你的容器,你如何使用它,你可以修改它,等等。也许你可以在不修改容器的情况下测试它,而是使用特殊的容器元素类型 - 跟踪副本和移动。

几个不同的容器和一些独立的模板化功能。大多数情况下,它是围绕STL库类型的包装器,如deque,list,map,set等。

2 个答案:

答案 0 :(得分:1)

添加一个布尔字段,在构造对象时将其设置为false。在移动构造函数和移动赋值运算符中,将true指定给要移动的对象中的该字段。

答案 1 :(得分:1)

  

是否有一种好的测试方法可以确保没有复制对象?

您可以尝试以下检查:

live demo

#include <boost/container/vector.hpp>
#include <iostream>
#include <ostream>
#include <vector>
#include <string>

using namespace boost;
using namespace std;

struct Test
{
    bool copied;
    Test()
        : copied(false)
    {
    }
    Test(const Test&)
        : copied(true)
    {
    }
};

template<typename Container>
void check_move_constructor()
{
    Container from(1);
    Container to(boost::move(from));
    cout << "\tmove constructor is" << (to[0].copied ? " not" : "") << " working" << endl;
}

template<typename Container>
void check_move_assignment()
{
    Container from(1);
    Container to;
    to=boost::move(from);
    cout << "\tmove assignment is" << (to[0].copied ? " not" : "") << " working" << endl;
}

template<typename Container>
void check_move(const string &name)
{
    cout << name << " :" << endl;
    check_move_constructor< Container >();
    check_move_assignment< Container >();
    cout << string(16,'_') << endl;
}

int main()
{
    cout << boolalpha;
    check_move< container::vector<Test> >("boost::container::vector");
    check_move< vector<Test> >("std::vector");
    return 0;
}

MSVC2008输出:

boost::container::vector :
        move constructor is working
        move assignment is working
________________
std::vector :
        move constructor is not working
        move assignment is not working
________________

注意,在这段代码中我使用了lvalues的显式移动,因此Copy-elision无法在这里工作。







P.S。另一种方法是检查生成的汇编代码。例如,MSVC上的/ FA编译器选项或GCC上的-S。

您可以使用特殊功能调用标记感兴趣的地方:

__declspec(noinline) void asm_marker(int line) { volatile int i=line; };
#define ASM_MARKER asm_marker(__LINE__)

将该标记放在代码中:

    ASM_MARKER;
    func_of_interest();
    ASM_MARKER;

Asm代码可能如下所示:

    mov     ecx, 235                                ; 000000ebH
    call    ?asm_marker@@YAXH@Z                     ; asm_marker
    mov     edi, r12d
    lea     rcx, QWORD PTR [rdi+rdi*4]
    mov     rax, QWORD PTR vec$[rsp]
    lea     r9, QWORD PTR [rax+rcx*8]
    mov     rbx, QWORD PTR vec$[rsp+32]
    mov     ecx, 237                                ; 000000edH
    call    ?asm_marker@@YAXH@Z                     ; asm_marker   
相关问题