我与尝试shared_ptr,并make_shared从C++ 11和编程的小玩具的例子来看看调用时什么是实际发生的事情make_shared.作为基础设施,我使用llvm/clang 3.0以及XCode4中的llvm std c ++库.
class Object
{
public:
Object(const string& str)
{
cout << "Constructor " << str << endl;
}
Object()
{
cout << "Default constructor" << endl;
}
~Object()
{
cout << "Destructor" << endl;
}
Object(const Object& rhs)
{
cout << "Copy constructor..." << endl;
}
};
void make_shared_example()
{
cout << "Create smart_ptr using make_shared..." << endl;
auto ptr_res1 = make_shared<Object>("make_shared");
cout << "Create smart_ptr using make_shared: done." …Run Code Online (Sandbox Code Playgroud) 从C++ 11开始,由于几个原因,开发人员倾向于将智能指针类用于动态生命周期对象.而对于那些新的智能指针类,标准,甚至建议不使用运营商,new而是建议使用make_shared或make_unique避免一些容易出错.
如果我们喜欢使用智能指针类shared_ptr,我们可以构建一个类似的,
shared_ptr<int> p(new int(12));
Run Code Online (Sandbox Code Playgroud)
我们还希望将自定义删除器传递给智能指针类,
shared_ptr<int> p(new int(12), deleter);
Run Code Online (Sandbox Code Playgroud)
另一方面,如果我们喜欢使用make_shared分配,例如.int,而不是使用new和shared_ptr构造函数,就像上面的第一个表达式,我们可以使用
auto ip = make_shared<int>(12);
Run Code Online (Sandbox Code Playgroud)
但是,如果我们也希望将自定义删除器传递给make_shared,那么有没有正确的方法呢?好像编译器,至少gcc,给出错误,
auto ip = make_shared<int>(12, deleter);
Run Code Online (Sandbox Code Playgroud) 在cppref中,以下内容一直持续到C++ 17:
f(std::shared_ptr<int>(new int(42)), g())如果g在之后调用new int(42)并抛出异常,则可能导致内存泄漏的代码,同时f(std::make_shared<int>(42), g())是安全的,因为两个函数调用永远不会交错.
我想知道在C++ 17中引入了哪些更改使其不再适用.
我感兴趣的是这两行代码是否相同:
shared_ptr<int> sp(new int(1)); // double allocation?
shared_ptr<int> sp(make_shared<int>(1)); // just one allocation?
Run Code Online (Sandbox Code Playgroud)
如果这是真的,有人可以解释为什么在第二行只有一个分配?
buffer = new char[64];
buffer = std::make_shared<char>(char[64]); ???
Run Code Online (Sandbox Code Playgroud)
你可以使用make_shared<>()?为数组分配内存吗?
我可以: buffer = std::make_shared<char>( new char[64] );
但这仍然涉及呼唤新的,这是我的理解make_shared更安全,更有效.
a的控制块shared_ptr保持活动,同时存在至少一个weak_ptr存在.如果创建共享指针make_shared,则意味着保持分配对象的整个内存.(对象本身被正确销毁,但由于控件块和对象的内存分配在一个块make_shared中,因此它们只能一起解除分配.)
我的理解是否正确?
看起来这种行为代表了一个问题,例如在着名的"缓存示例"中.对象的内存将永远分配.
这在任何实际情况下都是一个问题吗?应该shared_ptr在这种情况下使用构造函数创建(大对象和意图使用weak_ptrs)?
考虑以下代码:
#include <memory>
#include <iostream>
class SomeClass {
public:
SomeClass() {
std::cout << "SomeClass()" << std::endl;
}
~SomeClass() {
std::cout << "~SomeClass()" << std::endl;
}
void* operator new(std::size_t size) {
std::cout << "Custom new" << std::endl;
return ::operator new(size);
}
void operator delete(void* ptr, std::size_t size) {
std::cout << "Custom delete" << std::endl;
::operator delete(ptr);
}
};
int main() {
std::shared_ptr<SomeClass> ptr1(new SomeClass);
std::cout << std::endl << "Another one..." << std::endl << std::endl;
std::shared_ptr<SomeClass> ptr2(std::make_shared<SomeClass>());
std::cout << std::endl …Run Code Online (Sandbox Code Playgroud) 我的问题shared_ptr与make_sharedC++ 11有关.我有两个向量,第一个存储智能指针,第二个存储原始指针.第一个向量就像我已经过了一样,但是vector2只是令人困惑......
#include <iostream>
#include <vector>
#include <memory>
int main() {
std::vector<std::shared_ptr<int>> vector1;
vector1.push_back(std::make_shared<int>(1));
vector1.push_back(std::make_shared<int>(2));
vector1.push_back(std::make_shared<int>(3));
std::vector<int*> vector2;
vector2.push_back(std::make_shared<int>(4).get());
vector2.push_back(std::make_shared<int>(5).get());
vector2.push_back(std::make_shared<int>(6).get());
std::cout << "vector1 values:" << std::endl;
for(auto &value: vector1) { std::cout << *value << std::endl; }
std::cout << "vector2 values:" << std::endl;
for(auto &value: vector2) { std::cout << *value << std::endl; }
return 0;
}
Run Code Online (Sandbox Code Playgroud)
vector1 values:
1
2
3
vector2 values:
6
6
6
Run Code Online (Sandbox Code Playgroud)
我意识到创建原始指针并且不尝试转换智能指针会更简单但是让我很好奇知道为什么会发生这种情况?另外为什么每次推送都会改变vector2中的所有值?
以下是我在stackoverflow中发现的一些问题,但他们没有回答我的问题,或者我不明白答案......
Boost的make_shared()功能有望在尝试创建时具有异常安全性shared_ptr.
为什么没有make_scoped()相应的?有一个共同的最佳做法吗?
这是一个对我来说似乎不安全的boost::scoped_ptr文档中的代码示例:
boost::scoped_ptr<Shoe> x(new Shoe);
Run Code Online (Sandbox Code Playgroud)
这行代码将按顺序执行以下三项操作:
ShoeShoeboost::scoped_ptr<Shoe>如果构造函数Shoe抛出异常, 内存将被泄露. (见R.费尔南德斯Martinho的答案) 的scoped_ptr,因为它没有被构建但不会处理重新分配.
这是疏忽吗?还是有一个我没注意到的解决方案?
C++的new有一个选项可以返回空指针,而不是在分配失败时抛出bad_alloc异常.
Foo * pf = new(std::nothrow) Foo(1, 2, 3);
Run Code Online (Sandbox Code Playgroud)
(是的,我理解这只会阻止new抛出bad_alloc;它不会阻止Foo的构造函数抛出异常.)
如果你想使用共享指针而不是原始指针,你通常应该使用make_shared,因为它对控制块的分配很聪明.
auto pf = std::make_shared<Foo>(1, 2, 3);
Run Code Online (Sandbox Code Playgroud)
make_shared封装了new,这使得(?)无法选择nothrow版本.因此,您似乎必须放弃make_shared并明确调用new.
std::shared_ptr<Foo> pf(new(std::nothrow) Foo(1, 2, 3));
Run Code Online (Sandbox Code Playgroud)
这消除了使用Foo分配控制块的优化,并且控制块分配可能独立于Foo分配而失败,但我不想关注它.让我们假设控制块很小,所以它的分配在实践中永远不会失败.这是为我担心的Foo分配空间的失败.
有没有办法获得make_shared的单一分配优势,同时保留在为Foo分配空间时简单地获取空指针而不是bad_alloc异常的能力?
c++ ×10
make-shared ×10
c++11 ×6
shared-ptr ×6
boost ×1
c++17 ×1
clang ×1
libc++ ×1
nothrow ×1
scoped-ptr ×1
weak-ptr ×1