在Visual Studio 2010/2011中缺少可变参数模板(仍然!)时,采用大量参数的构造函数可能会出现问题.例如,以下内容将无法编译:
MyMaterials.push_back(std::make_shared<Material>(MyFacade,
name,
ambient,
diffuse,
specular,
emissive,
opacity,
shininess,
shininessStrength,
reflectivity,
bumpScaling,
maps,
mapFlags));
Run Code Online (Sandbox Code Playgroud)
,因为它有13个参数,我认为make_shared是从arg0限制到arg9.显而易见的解决方案是两部分构建,但我希望避免这种情况.除了使用new而不是make_shared 之外,还有其他可能吗?
谢谢.
据我所知,make_shared<T>(...)可以提供一些内存分配优化(它可以在与T类实例相同的内存块中分配引用计数器).
enable_shared_from_this提供相同的优化吗?所以:
class T : std::enable_shared_from_this<T> {};
...
auto t = std::shared_ptr<T>(new T);
Run Code Online (Sandbox Code Playgroud)
是相同的:
class T {};
...
auto t = std::make_shared<T>();
Run Code Online (Sandbox Code Playgroud)
如果不考虑sizeof(T).
我编写了一个带有受保护构造函数的类,因此只能使用静态create()函数生成新实例,该函数将shared_ptr返回给我的类.为了提供有效的分配,我想在create函数中使用boost :: make_shared,但是编译器抱怨我的类构造函数在boost :: make_shared中受到保护.我决定将我的boost :: make_shared作为我班上的朋友,但我对语法感到困惑.我试过了
template< class T, class A1, class A2 >
friend boost::shared_ptr<Connection> boost::make_shared(const ConnectionManagerPtr&, const std::string&);
Run Code Online (Sandbox Code Playgroud)
但是编译器给了我语法错误.请帮忙.
在make_shared的boost文档中,它说:
除了方便和风格之外,这样的函数也是异常安全且相当快的,因为它可以对对象及其相应的控制块使用单个分配,从而消除了shared_ptr的构造开销的很大一部分.
我不明白"单一分配"的含义,这是什么意思?
事后看来,给定的是make_shared,如果shared_ptr用C++ 11引入它,会有一个带有原始指针的构造函数吗?
有没有强大的论据或用例支持这个构造函数?
这本来是可以避免的有据可查的陷阱异常安全和内存分配/性能优势利用make_shared.
我认为需要shared_ptr构建的另一个优点make_shared是它可能是引擎盖下的单个指针,降低了它的内存使用并使atomic_compare_exchange之类的东西变得更简单(并且可能更高效).(请参阅C++中的演示文稿)
编辑
我知道一个shared_ptr基本上是一个intrusive_ptr(对象和控制块合并)会缺少当前std :: shared_ptr所具有的功能.喜欢:
将对象与控制块分开释放的能力(如果你长期生活在weak_ptrs中,这很好)
与提供原始指针的库的兼容性以及释放它们的责任
使用自定义删除程序保留任意资源的能力(或者对于非拥有指针没有删除程序)
能够在保持父对象存活的同时指向子对象(例如成员).
我建议的是,这些功能可能不常用(或者在使用它作为raii-wrapper的情况下)可能不是最合适的,以保证额外的费用:
在C++ 98世界中(引入了shared_ptr),make_shared不太实用且用户友好性较差(缺乏完美的转发需要参考包装器和缺少可变参数模板使得实现笨重).
这是我的代码。编译时出现错误
\n\n\n\n\n\xe2\x80\x98geometry\xe2\x80\x99 之前的声明符无效
\n
在第 16 行和第 48 行,我不确定我做错了什么。请指教。
\n\n#include <iostream>\n#include <memory>\n#include <vector>\nusing namespace std;\nclass FactGeometry { //Factory class\npublic:\n static std::shared_ptr<FactGeometry>geometry( int choice );\n virtual void calcArea() = 0;\n};\n\nclass CalcRectangle :public FactGeometry {\n void calcArea() {\n double ll, bb, Area;\n std::cout << "\\nEnter the length = ";\n std::cin >> ll;\n std::cout << "\\nEnter the breadth = ";\n std::cin >> bb;\n Area = ll * bb;\n std::cout << "\\nArea = " << Area;\n }\n}; //end class\n\nclass CalcTraingle …Run Code Online (Sandbox Code Playgroud) 考虑以下:
class DirectoryIterator;
namespace detail {
class FileDataProxy;
class DirectoryIteratorImpl
{
friend class DirectoryIterator;
friend class FileDataProxy;
WIN32_FIND_DATAW currentData;
HANDLE hFind;
std::wstring root;
DirectoryIteratorImpl();
explicit DirectoryIteratorImpl(const std::wstring& pathSpec);
void increment();
bool equal(const DirectoryIteratorImpl& other) const;
public:
~DirectoryIteratorImpl() {};
};
class FileDataProxy //Serves as a proxy to the WIN32_FIND_DATA struture inside the iterator.
{
friend class DirectoryIterator;
boost::shared_ptr<DirectoryIteratorImpl> iteratorSource;
FileDataProxy(boost::shared_ptr<DirectoryIteratorImpl> parent) : iteratorSource(parent) {};
public:
std::wstring GetFolderPath() const {
return iteratorSource->root;
}
};
}
class DirectoryIterator : public boost::iterator_facade<DirectoryIterator, detail::FileDataProxy, std::input_iterator_tag> …Run Code Online (Sandbox Code Playgroud) 我试图使用std :: make_shared将'this'传递给构造函数
例:
// headers
class A
{
public:
std::shared_ptr<B> createB();
}
class B
{
private:
std::shared_ptr<A> a;
public:
B(std::shared_ptr<A>);
}
// source
std::shared_ptr<B> A::createB()
{
auto b = std::make_shared<B>(this); // Compiler error (VS11 Beta)
auto b = std::make_shared<B>(std::shared_ptr<A>(this)); // No compiler error, but doenst work
return b;
}
Run Code Online (Sandbox Code Playgroud)
然而,这不能正常工作,任何建议我如何正确传递这个作为参数?
(使用Visual Studio 2010)我正在尝试在我的项目中创建现有类的shared_ptr(类是在std :: shared_ptr存在之前写的十年).该类采用非const指针指向另一个对象,它的空参数构造函数是私有的.
class Foobar {
public:
Foobar(Baz* rBaz);
private:
Foobar();
}
Run Code Online (Sandbox Code Playgroud)
当我尝试创建一个shared_ptr时,事情进展不顺利:
Baz* myBaz = new Baz();
std::shared_ptr<Foobar> sharedFoo = std::make_shared<Foobar>(new Foobar(myBaz));
Run Code Online (Sandbox Code Playgroud)
在VS2010上,这给了我
error C2664: 'Foobar::Foobar(const Foobar &)' : cannot convert parameter 1 from 'Foobar *' to 'const Foobar &'
3> Reason: cannot convert from 'Foobar *' to 'const Foobar'
Run Code Online (Sandbox Code Playgroud)
由于某种原因,它似乎是调用复制构造函数Foobar而不是构造函数Baz*.
我也不确定这个cannot convert from 'Foobar *' to 'const Foobar'部分.我最好的解释是我的模板类型shared_ptr<Foobar>是错误的.我做了,shared_ptr<Foobar*>但这似乎是错的,我见过的所有例子都没有使该类型成为原始指针.
似乎shared_ptr<Foobar*>正确地编译所有内容,但是Foobar当所有内容shared_ptr都超出范围时,是否会阻止对象被正确删除?
编辑: …
我第一次使用boost :: make_shared来创建共享指针指向的对象.主要是因为我们的代码太慢而且单个分配确实有助于提高性能.
在修复了一些内存泄漏"硬手动方式"后,我决定通过覆盖所有相关类的新操作符来实现一个简单的内存泄漏检测器,只是为了计算在我们的应用程序中的特定点仍然存活的对象.我之前已经多次实现过,并且惊讶地发现我的代码不再检测到任何对象.
我想我所要做的就是覆盖"placement new"而不是"normal"operator new,因为make_shared的boost网站文档中有以下内容:
"效果:分配存储器适合类型T的对象,并在其中通过放置新的表达新(PV)T()或新的(PV)构造一个对象T(标准::向前(参数)...) allocate_shared.使用a的副本来分配内存.如果抛出异常,则无效."
我的位置新也没有被调用.我写了一个小测试程序来重现行为:
#include <iostream>
using namespace std;
#include "boost/shared_ptr.hpp"
#include "boost/make_shared.hpp"
class Test
{
public:
Test() { cout << "Test::Test()" << endl; }
void* operator new (std::size_t size) throw (std::bad_alloc) {
cout << "Test new" << endl;
return malloc(size);
}
void* operator new (std::size_t size, const std::nothrow_t& nothrow_constant) throw() {
cout << "Test non-throwing new" << endl;
return malloc(size);
}
void* operator new (std::size_t size, void* ptr) throw() {
cout << …Run Code Online (Sandbox Code Playgroud) make-shared ×10
c++ ×9
shared-ptr ×6
boost ×4
c++11 ×4
constructor ×1
friend ×1
new-operator ×1
stl ×1
templates ×1
this ×1