2016-03-07 3 views
2

В контексте, как тот, который следует:Перемещение ресурсов из общего класса

template <class T> 
struct MyStruct 
{ 
    T resource; 
    decltype(auto) getResource() 
    { 
     return std::move(resource); 
    }  
}; 

мой getResource способ делать то, что я ожидаю, что это сделать, т.е. переместить resource элемент из класса? Я хочу использовать его в тех случаях, когда MyStruct больше не будет использоваться, и это нормально, чтобы «украсть» память.

+4

Если украсть что-то вы бы лучше придерживаться какого-то более сложного названия - насколько я могу судить, видя ** ** получить человек обычно не ожидаем модификация. – ixSci

+0

decltype (auto) is C++ 14 –

ответ

2

С

template <class T> 
struct MyStruct 
{ 
    T resource; 
    decltype(auto) getResource() 
    { 
     return std::move(resource); 
    } 
}; 

decltype(auto) является T&&. но T&& сам по себе не крадет ресурс (но позволяет его украсть неявно).

Альтернативой будет

template <class T> 
struct MyStruct 
{ 
    T resource; 
    T takeResource() 
    { 
     return std::move(resource); 
    } 
}; 

Здесь, как только takeResource называется, ресурс был передан.

Так, например

MyStruct<std::unique_ptr<int>> foo; foo.resource = std::make_unique<int>(42); 
*foo.get_resource() = 51; // No transfer ownership, just get a reference 
*foo.get_resource() = 69; // still works. 

но

*foo.get_resource() = 51; // Transfer ownership, and resource will be released here 
*foo.get_resource() = 69; // dereferencing nullptr -> UB. 
2

Все зависит от того, что такое T и как его конструктор движения был написан. Если это, например, int, он просто копирует его. Если это std::unique_ptr, он будет делать то, что вы ожидаете точно.

Для лучшего понимания см этот пример, пожалуйста:

#include <iostream> 
#include <string> 
class copyable{ 
public: 
    copyable():x(0){}; 
    ~copyable()=default; 
    copyable(copyable const&)=default; 
    copyable(copyable&&)=default; 

    int x; 
}; 

class moveable{ 
public: 
    moveable():x(new int{0}){}; 
    ~moveable(){ 
     delete[] x; 
    }; 
    moveable(moveable const&)=delete; 
    moveable(moveable&& other){ 
     this->x=other.x; 
     other.x=nullptr; 
    }; 

    int* x; 
}; 

template <class T> 
struct MyStruct 
{ 
    T resource; 
    decltype(auto) getResource() 
    { 
     return std::move(resource); 
    }  
}; 

int main() 
{ 
    MyStruct<copyable> a; 
    std::cout << a.resource.x <<"\n"; 

    MyStruct<moveable> b; 
    std::cout << "address: "<< b.resource.x << "\tval: " << *b.resource.x <<"\n\n"; 

    auto temp_a=a.getResource(); 
    std::cout << temp_a.x <<"\n"; 

    auto temp_b=b.getResource(); 
    std::cout << "address: "<< temp_b.x << "\tval: " << *temp_b.x <<"\n\n"; 


    std::cout << a.resource.x <<"\n"; 
    std::cout << "address: "<< b.resource.x << "\tval: " << /* *b.resource.x << THIS IS UB */ "\n\n"; 

} 

Выход:

0 
address: 0x2d366f0 val: 0 

0 
address: 0x2d366f0 val: 0 

0 
address: 0 val: 

Live Demo

0

std::move не двигается сама по себе, это небольшой misnoma , std::move здесь обеспечивает только rvalue. Ваш тип T также должен иметь конструктор, позволяющий фактически его перемещать.

В целом вы не можете гарантировать, что ваш ресурс не скопирован.

Пройдите unique pointer, если вы хотите быть явным, кто владеет уникальным ресурсом в определенное время. уникальный указатель является общим и, вероятно, будет тем, что вы в конечном итоге реализуете, если усовершенствовать свой дизайн достаточно долго.

+0

std :: uniuqe_ptr будет выделять память в куче, которая может оказаться непригодной для OP –

+0

@HumamHelfawi 'unique_ptr' не выделяет память в куче. 'make_unique' может. – juanchopanza

+0

@juanchopanza кажется, что я что-то пропустил. Вы имеете в виду, что я могу сделать std :: unique_ptr, чтобы указать на стек выделенного объекта? –

Смежные вопросы