我偶然发现了这种行为当使用std::weak_ptr和std::make_shared我发现这一点都不奇怪.我正在使用C++ 11.
#include <iostream>
#include <memory>
int main()
{
std::weak_ptr<int> weak;
std::shared_ptr<int> shared {std::make_shared<int>(42)};
weak = shared;
std::cout << "Meaning of life: " << *weak.lock() << std::endl;
weak = std::make_shared<int>(23);
std::cout << "Meaning of life: " << *weak.lock() << std::endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
第一次std::cout打印很好,第二次给我一个段错误.我试着看的网页std::weak_ptr,并std::shared_ptr在cppreference,但我还是不明白为什么会这样.必须创建一个临时对象对我来说感觉很麻烦,这是在C++ 14中解决的问题还是我没有看到的东西?
谢谢!
我的问题是这个说法:
如果任何std :: weak_ptr在所有共享所有者的生命周期结束后引用由std :: make_shared创建的控制块,则T占用的内存将持续存在,直到所有弱所有者都被销毁,如果sizeof(T)是大.资源
我在这里读到,这个对象一直存在,直到最后一个weak_ptr存在.它是使用make_shared自由对象,循环引用self还是永远存在于内存中?
例如:
struct A
{
std::weak_ptr<A> parent;
}
void fn()
{
auto a=std::make_shared<A>();
a->parent = a;
} // Will it destroy here or not?
Run Code Online (Sandbox Code Playgroud) 我知道我可以通过将自定义类及其后代operator new设为私有来防止普通堆分配,但是有什么方法可以防止库的用户调用std::make_shared自定义类(或其后代)?显然,仅使operator new私有成为类并不能阻止它。
请注意,我不想完全阻止以任何方式创建共享指针,因为我打算仍然能够std::shared_ptr通过调用静态生成器方法来为自定义类生成一个,但是我仍然想防止其他人尝试调用std::make_shared直接在我的课上。
编辑:
为了解决下面的查询,我的最终目标是从原始指针中提取shared_ptr的灵活且可重用的机制。std::enable_shared_from_this遗憾的是,在继承方面,尤其是在多重继承方面,它不是很友好。
另外,因为我打算将此作为在使用CRTP的模板类中使用,所以子类T需要显式地使它继承自朋友的模板化父类使其变得可以访问,这会使事情复杂化。私有构造函数。
据我所知,如果你使用std::make_shared它,它会在底层对象的同时创建引用计数对象.
但是,如果smart_ptr指向的对象指针大于56字节,那么引用计数器最终不会位于不同的高速缓存行中(因为高速缓存行是64字节)?
我正在尝试遵循Herb Sutter的C++指南,在这种情况下更喜欢unique_ptr原始指针和shared_ptr.赞成的一个论点std::unique_ptr是shared_ptr在某些时候需要的可兑换性.
在我来说,我有一个vector的unique_ptr,我需要传递给需要的方法vector的shared_ptr.我希望能写出类似的东西:
for (auto &uniquePtr : vectorUnique)
vectorShared.push_back(make_shared<Abstract>(move(uniquePtr));
Run Code Online (Sandbox Code Playgroud)
这为我的Xcode 7.1基于工具链配置的以下错误C++11:
错误:字段类型'Abstract'是一个抽象类.
似乎STL Abstract在我使用时试图保持一个具体的类型实例make_shared.这似乎使Sutter先生的建议在许多情况下变得不可行,所以我确信我一定做错了!我求助于写作:
for (auto &uniquePtr : vectorUnique) {
auto ptr = uniquePtr.get();
auto shared = shared_ptr<Abstract>(ptr);
vectorShared.push_back(shared);
uniquePtr.release();
}
Run Code Online (Sandbox Code Playgroud)
有一个更好的方法吗?
我试着为这个问题写一个标题,比如10分钟,你会看到我最终失败了.[编者注:我认为我已经解决了这个问题.]
我正在阅读Herb Sutter的博客,主题是使用std :: make_shared及其缺点和优点.请看附上的照片:
这是一篇非常有趣的文章的一小部分,我强烈建议人们阅读.我的问题是关于这句话:
"弱引用"计数用于跟踪当前正在观察对象的weak_ptrs的数量.当最后一个弱引用消失时,共享内务控制块被销毁并解除分配(并且如果共享对象尚未释放,则将其解除分配).**
我真的不明白这个说法.最初,当我们创建一个std::shared_ptrby,make_shared例如auto sp1 = make_shared<widget>();,当前没有弱ptrs正在观察sp1,所以当它shared_ptr以通常的方式超出范围时将被删除.
那么添加弱引用如何改变这种行为呢?有人能解释一下吗?
make_shared()从理论上讲,和之间的一个区别shared_ptr是内存分配技术。make_shared()应该使用单个块,而shared_ptr应该使用两个块。
一个make_shared()缺点应该是,即使有一个活着的内存也无法释放weak_ptr。
有人可以解释为什么这个程序的输出总是相同的,独立于我用来创建的函数shared_ptr?
#include <iostream>
#include <memory>
class mc
{
public:
mc(int p):p_{p} {std::cerr<<"Constructor"<<std::endl;}
~mc() { std::cerr<<"Destructor"<<std::endl;}
private:
int p_;
};
std::weak_ptr<mc> wp3;
int main()
{
auto sp=std::make_shared<mc>(4);
auto sp2=sp;
auto sp3{sp};
wp3=std::weak_ptr<mc>{sp};
sp2.reset();
sp3.reset();
sp.reset();
for (int i =0;i< 5;i++) {std::cerr<<sp.use_count()<<std::endl;}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我期待最后调用析构函数方法,因为它weak_ptr仍然存在,为什么没有发生?
我正在使用gcc 4.6.2.
我正在尝试在向量shared_ptr中推送back_back.
但gcc每次都给我一个错误.
这是我的代码行:
std::vector< std::tr1::shared_ptr<Process> > procs;
std::string line;
while (getline(file, line) && line.find(JobMask) != std::string::npos)
{
std::string procName = line.substr(line.find(JobMask) + JobMask.size());
std::vector<Instruction> procInstructions = extractProgram(file);
std::queue<int> procInputs = extractInputs(file);
if (!procInstructions.empty())
procs.push_back(std::make_shared<Process>(Process(procName, procInputs, procInstructions))); //line 51
}
return procs;
Run Code Online (Sandbox Code Playgroud)
我的gcc给出的错误是:
Process.cpp: In static member function 'static std::vector<std::tr1::shared_ptr<RMMIX::Process> > RMMIX::Process::createProcesses(const string&)':
Process.cpp:51:95: error: no matching function for call to 'std::vector<std::tr1::shared_ptr<RMMIX::Process> >::push_back(std::shared_ptr<RMMIX::Process>)'
Process.cpp:51:95: note: candidates are:
/usr/lib/gcc/x86_64-pc-linux-gnu/4.6.2/include/g++-v4/bits/stl_vector.h:826:7: note: void std::vector<_Tp, _Alloc>::push_back(const value_type&) [with _Tp = std::tr1::shared_ptr<RMMIX::Process>, _Alloc = …Run Code Online (Sandbox Code Playgroud) 考虑这个shared_ptr<T>以各种方式构造并返回的示例:
#include <memory>
#include <iostream>
class Base
{
public:
virtual ~Base() {}
Base(int y) : y_(y) {}
int y_;
};
class Derived : public Base
{
public:
Derived(int y, int z) : Base(y), z_(z) {}
int z_;
};
std::shared_ptr<Base> A()
{
return std::shared_ptr<Base>(new Derived(1, 2));
}
std::shared_ptr<Base> B()
{
std::shared_ptr<Derived> result = std::make_shared<Derived>(Derived(1, 2));
return result;
}
std::shared_ptr<Base> C()
{
std::shared_ptr<Base> result = std::make_shared<Base>(Derived(1, 2));
return result;
}
std::shared_ptr<Base> D()
{
return std::make_shared<Base>(Derived(1, 2));
}
int main(int argc, …Run Code Online (Sandbox Code Playgroud) some_vector.push_back(make_shared<ClassName>());
some_vector.emplace_back(make_shared<ClassName>());
Run Code Online (Sandbox Code Playgroud)
我想检查一下我的理解是否正确,对于make_shared返回对象的所有其他函数,这两个调用是相同的。这里make_shared将创建一个新的shared_ptr,然后这个指针都将在被转移到容器中push_back和emplace_back。这是正确的,还是会有一些区别?
make-shared ×10
c++ ×9
c++11 ×7
shared-ptr ×7
weak-ptr ×3
c++17 ×2
abstract ×1
c++14 ×1
class ×1
gcc4 ×1
unique-ptr ×1
vector ×1