std
全程假设命名空间.
因此,C++ 14委员会草案N3690定义std::make_unique
如下:
[n3690: 20.9.1.4]:
unique_ptr
创作 [unique.ptr.create]
template <class T, class... Args> unique_ptr<T> make_unique(Args&&... args);
1备注:除非
T
不是数组,否则此函数不应参与重载决策.
2返回:unique_ptr<T>(new T(std::forward<Args>(args)...)).
template <class T> unique_ptr<T> make_unique(size_t n);
3备注:除非
T
是未知范围的数组,否则此函数不应参与重载决策.
4返回:unique_ptr<T>(new typename remove_extent<T>::type[n]()).
template <class T, class... Args> unspecified make_unique(Args&&...) = delete;
5备注:除非
T
是已知绑定的数组,否则此函数不应参与重载决策.
现在,在我看来,这与泥浆一样清晰,我认为需要更多的阐述.但是,除了这篇评论之外,我相信我已经解释了每个变体的含义:
template <class T, class... Args> unique_ptr<T> make_unique(Args&&... args);
你make_unique
的非数组类型的标准.据推测,"注释"表示某种形式的静态断言或SFINAE技巧是为了防止模块在T
数组类型时被成功实例化.
在高级别,将其视为相当于的智能指针T* ptr = new T(args);
.
template <class T> …
我有一个关于std::unique_ptr
和的问题std::shared_ptr
.我知道有很多关于何时使用哪一个的问题,但我仍然不确定我是否正确理解它.我在某处读到了智能指针的默认选择std::unique_ptr
,但据我了解,我应该更喜欢使用std::shared_ptr
.例如,我有:
class B;
class A
{
private:
B* b;
public:
B* getB();
};
A::getB()
{
return b;
}
Run Code Online (Sandbox Code Playgroud)
所以基本上类A
拥有指向类型对象的指针,B
并且有一个返回该指针的方法.如果我创建了getter,我假设其他一些类可以访问这个指针,因此它应该shared_ptr
代替unique_ptr
.我是对的,还是我还没有得到它?
在我从前一个问题的答案中提示之后编写了一些东西,我遇到了重载Scene :: addObject的问题.
重申相关位并使其自包含,尽可能少的细节:
Interface
,其中有Foo
S和Bar
S;Scene
拥有这些物品的人;Foo
s应该是unique_ptr
s和Bar
s将shared_ptr
在我的主要(由于前一个问题中解释的原因);main
它们传递到Scene
实例,其取得所有权.最小的代码示例是这样的:
#include <memory>
#include <utility>
class Interface
{
public:
virtual ~Interface() = 0;
};
inline Interface::~Interface() {}
class Foo : public Interface
{
};
class Bar : public Interface
{
};
class Scene
{
public:
void addObject(std::unique_ptr<Interface> obj);
// void addObject(std::shared_ptr<Interface> obj);
};
void Scene::addObject(std::unique_ptr<Interface> obj)
{
}
//void …
Run Code Online (Sandbox Code Playgroud) 我正在尝试使用C++ 0x unique_ptr
类,map
如下所示:
// compile with `g++ main.cpp -std=gnu++0x`
#include <string.h>
#include <map>
#include <memory>
using namespace std;
struct Foo {
char *str;
Foo(char const *str_): str(strdup(str_)) {}
};
int main(void) {
typedef std::map<int, unique_ptr<Foo>> Bar;
Bar bar;
auto a = bar.insert(Bar::value_type(1, new Foo("one")));
return 0;
}
Run Code Online (Sandbox Code Playgroud)
但是GCC给了我以下错误(缩短了,我认为这是相关部分,请在您自己的C++编译器上测试):
main.cpp:19: instantiated from here /usr/include/c++/4.4/bits/unique_ptr.h:214: error: deleted function ‘std::unique_ptr::unique_ptr(const std::unique_ptr&) [with _Tp = Foo, _Tp_Deleter = std::default_delete]’ /usr/include/c++/4.4/bits/stl_pair.h:68: error: used here
我真的不确定我做错了什么,这适用于MSVC.我发现了非常相似的问题,看似相似,但是他们的解决方案对我不起作用.
matt@stanley:/media/data/src/c++0x-test$ gcc --version …
我正在创建一个与一些Windows API代码交互的类,现在我必须初始化的一个指针是通过调用初始化它的本机函数来完成的.
我的指针是std::unique_ptr
带有自定义删除器的类型,它调用所提供的WinAPI删除函数,但是我不能将带有&address-of运算符的unique_ptr传递给init-function.为什么?
我创建了一个演示我的问题的示例:
#include <memory>
struct foo
{
int x;
};
struct custom_deleter {};
void init_foo(foo** init)
{
*init = new foo();
}
int main()
{
std::unique_ptr<foo, custom_deleter> foo_ptr;
init_foo(&foo_ptr);
}
Run Code Online (Sandbox Code Playgroud)
编译器咆哮并说:
source.cpp: In function 'int main()':
source.cpp:19:21: error: cannot convert 'std::unique_ptr<foo, custom_deleter>*' to 'foo**' for argument '1' to 'void init_foo(foo**)'
Run Code Online (Sandbox Code Playgroud) 这是一个非常简单的问题.请考虑以下代码:
#include <iostream>
#include <memory>
typedef std::unique_ptr<void> UniqueVoidPtr;
int main() {
UniqueVoidPtr p(new int);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
使用以下命令使用cygwin(g ++ 4.5.3)进行编译g++ -std=c++0x -o prog file.cpp
就可以了.但是,使用Microsoft编译器(VS 2010或2013)进行编译时出现此错误:
C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\INCLUDE\memory(2067) : error C2070: 'void': illegal sizeof operand
C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\INCLUDE\memory(2066) : while compiling class template member function 'void std::default_delete<_Ty>::operator ()(_Ty *) const'
with
[
_Ty=void
]
C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\INCLUDE\type_traits(650) : see reference to class template instantiation 'std::default_delete<_Ty>' being compiled
with
[ …
Run Code Online (Sandbox Code Playgroud) 当我发现标准定义std::unique_ptr
并且std::shared_ptr
以两种完全不同的方式关于指针可能拥有的Deleter时,我认为这很奇怪.这是来自cppreference :: unique_ptr和cppreference :: shared_ptr的声明:
template<
class T,
class Deleter = std::default_delete<T>
> class unique_ptr;
template< class T > class shared_ptr;
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,unique_ptr将"Deleter"对象的类型"保存"为模板参数.这也可以通过稍后从指针中检索Deleter的方式看出:
// unique_ptr has a member function to retrieve the Deleter
template<
class T,
class Deleter = std::default_delete<T>
>
Deleter& unique_ptr<T, Deleter>::get_deleter();
// For shared_ptr this is not a member function
template<class Deleter, class T>
Deleter* get_deleter(const std::shared_ptr<T>& p);
Run Code Online (Sandbox Code Playgroud)
有人可以解释这种差异背后的理性吗?我明显赞成这个概念,unique_ptr
为什么这不适用于此shared_ptr
?另外,为什么get_deleter
在后一种情况下会成为非成员函数呢?
我有以下代码
class A {
public:
A(){}
~A(){}
private:
std::vector<std::unique_ptr<double> > x;
};
A f() {
A a;
return a;
}
int main() {
A a=f();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
除非我注释掉析构函数,否则它不会编译(gcc 4.7).实际上,我在代码中并不需要这个析构函数,我只是想将它用于调试目的.
但是,我不明白发生了什么,因此我担心我做错了什么.这里发生了什么?
我有一个函数需要返回一个指向类对象的指针myClass
.为此我正在使用std::unique_ptr
.
如果函数成功,它将返回一个指向带有数据的对象的指针.如果失败,它应该返回null
.
这是我的代码skelepton:
std::unique_ptr<myClass> getData()
{
if (dataExists)
... create a new myClass object, populate and return it ...
// No data found
return std::unique_ptr<myClass> (null); <--- Possible ?
}
Run Code Online (Sandbox Code Playgroud)
上main
:
main()
{
std::unique_ptr<myClass> returnedData;
returnedData = getData();
if (returnedData != null) <-- How to test for null ?
{
cout << "No data returned." << endl;
return 0;
}
// Process data
}
Run Code Online (Sandbox Code Playgroud)
所以这里是我的问题:
a)是否null
可以使用std::unique_ptr
?(返回一个对象或)?
b)如果可能,如何实施?
c)如果不可能,有哪些替代方案? …
我无法理解为什么以下复制初始化无法编译:
#include <memory>
struct base{};
struct derived : base{};
struct test
{
test(std::unique_ptr<base>){}
};
int main()
{
auto pd = std::make_unique<derived>();
//test t(std::move(pd)); // this works;
test t = std::move(pd); // this doesn't
}
Run Code Online (Sandbox Code Playgroud)
A unique_ptr<derived>
可以移入a unique_ptr<base>
,那么为什么第二个语句有效但最后一个没有?执行复制初始化时是否不考虑非显式构造函数?
gcc-8.2.0的错误是:
conversion from 'std::remove_reference<std::unique_ptr<derived, std::default_delete<derived> >&>::type'
{aka 'std::unique_ptr<derived, std::default_delete<derived> >'} to non-scalar type 'test' requested
Run Code Online (Sandbox Code Playgroud)
从clang-7.0.0开始
candidate constructor not viable: no known conversion from 'unique_ptr<derived, default_delete<derived>>'
to 'unique_ptr<base, default_delete<base>>' for 1st argument
Run Code Online (Sandbox Code Playgroud)
现场代码可在此处获得.