我正在替换像:
这样的陈述auto pszOutBuffer = new char[dwSize];
ReadDataFromHttp(pszOutBuffer, dwSize);
if(dwSize>100)
ParseHttpData(pszOutBuffer);
...
delete []pszOutBuffer;
TO:
auto OutBufferPtr = make_unique<char[]>(dwSize);
auto pszOutBuffer = OutBufferPtr.get();
ReadDataFromHttp(pszOutBuffer, dwSize);
if(dwSize>100)
ParseHttpData(pszOutBuffer);
...
这样我就可以利用智能指针unique_ptr
。我希望保持变量pszOutBuffer
不变,因此Git提交中的更改变少,并且不需要重复unique_ptr.get()
。
使这个变得简单,阅读不那么冗长;我想编写一个宏MAKE_UNIQUE_PTR(type,size)
,它将是一个单独的语句(不两个,如上所示)。但是,这样的宏将不能像{1}}一样unqiue_ptr
,而在
pszOutBuffer
我可能会考虑编写一个函数模板,但是......如何在函数(auto pszOutBuffer = MAKE_UNIQUE_PTR(char, dwSize);
)之后保持unique_ptr
返回?
修改
使用此假设的宏/函数,代码将只是:
MAKE_UNIQUE_PTR
具有以下优势:
auto pszOutBuffer = MAKE_UNIQUE_PTR(char, dwSize);
ReadDataFromHttp(pszOutBuffer, dwSize);
if(dwSize>100)
ParseHttpData(pszOutBuffer);
...
仍然控制缓冲区的生命周期。unique_ptr
次调用。unique_ptr::get()
个调用。请注意,第一个代码是我手头的代码。没有宏,没有delete[]
- 只有遗留代码unique_ptr
和new
。是的......那些匈牙利符号变量。
答案 0 :(得分:4)
不幸的是,由于original proposal中显示的原因,我们不支持std::make_unique<T[N]>()
。但是,没有什么可以阻止您为数组(例如make_unique
)制作自己的make_unique_array
,如下所示:
template<typename T>
std::enable_if_t<std::is_array<T>::value, std::unique_ptr<T>>
make_unique_array(std::size_t const n) {
using RT = std::remove_extent_t<T>;
return std::unique_ptr<T>(new RT[n]);
}
答案 1 :(得分:1)
由于您已经在使用宏,因此可以编写一个可以创建两者的宏。这很丑陋,但确实有它的作用。
#define SmartMacro(pszOutBuffer, dwSize) \
auto pszOutBuffer##ptr = make_unique<char[]>(dwSize); \
auto pszOutBuffer = pszOutBuffer##ptr.get(); \
memset(pszOutBuffer, 0, dwSize);
// Usage
SmartMacro(buffer, 10);
// 'buffer' is the raw pointer
// 'bufferptr' is the unique pointer
答案 2 :(得分:1)
template<class T, class D>
struct smart_unique:std::unique_ptr<T,D> {
using std::unique_ptr<T,D>::unique_ptr;
operator T*()const{return this->get();}
operator T const*()const{return this->get();}
};
template<class T, class D>
struct make_smart_unique_t {
template<class...Ts>
smart_unique<T, D> operator()(Ts&&...ts)const{
return smart_unique<T,D>( new T(std::forward<Ts>(ts)...); );
}
template<class T0, class...Ts>
smart_unique<T, D> operator()(std::initializer_list<T0> il, Ts&&...ts)const{
return smart_unique<T,D>( new T(il, std::forward<Ts>(ts)...); );
}
};
template<class T, class D>
struct make_smart_unique_t<T[], D> {
smart_unique<T[], D> operator[](std::size_t N)const{
return smart_unique<T[],D>( new T[N]; );
}
template<class...Ts>
smart_unique<T[], D> operator()(Ts&&...ts)const{
return smart_unique<T[],D>( new T[sizeof...(Ts)]{std::forward<Ts>(ts)...}; );
}
};
template<class T, class D=std::default_delete<T>>
constexpr make_smart_unique_t<T,D> make_smart_unique{};
这应该支持:
auto pszOutBuffer = make_smart_unique<char[]>[dwSize];
ReadDataFromHttp(pszOutBuffer, dwSize);
if(dwSize>100)
ParseHttpData(pszOutBuffer);
以及:
auto pszDataBuffer = make_smart_unique<int[]>(1,2,3,4,5);
和
auto pszDataBuffer = make_smart_unique<int>();
不需要宏观魔法。
此处的设计很简单:make_smart_unique<scalar>
与make_unique
类似,但它会返回smart_unique
(隐式转换为T*
:非常小心!)< / p>
make_smart_unique<Array[]>
有两种不同的方式来调用它。使用[N]
创建一个传入大小的数组:使用(args...)
它创建一个元素数量大小的数组,并从每个arg构造每个元素。