- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有一个 char 指针,我需要转移其所有权,如果可能的话,我宁愿不必自己处理它的生命周期。内存是使用 malloc 分配的(这里没有选择)。
因此,我正在寻找类似 C++11 的 unique_ptr 之类的东西,它管理所有权并允许提供自定义 Deleter
。
正如标题所暗示的,虽然我无权访问 C++11 功能。据我所知,auto_ptr
并不是一个常见问题,因为它调用的是 delete
而不是 free
。
在这种情况下是否有合适的智能指针,还是我必须自己管理内存的释放?
最佳答案
作为自己编写的替代方法,您可以引入对 Boost 的依赖,并只使用 boost::shared_ptr
。
但为了比较,这里是基于 malloc
/free
的所有权转移指针的最小即用 C++11 和更高版本代码,例如 std::独特
:
template< class Type >
class My_ptr
{
private:
Type* p_;
My_ptr( My_ptr const& ) = delete;
operator=( My_ptr const& ) -> My_ptr& = delete;
public:
auto operator->() const
-> Type*
{ return p; }
auto operator*() const
-> Type&
{ return *p; }
~My_ptr() { free( p_ ); }
My_ptr( Type* p )
: p_( p )
{}
My_ptr( My_ptr&& other )
: p_( other.p_ )
{ other.p_ = nullptr; }
};
如您所见,C++11 中的代码并不多。
免责声明:以上代码未被编译器看到。
在 C++03 中,主要问题是如何使从函数返回智能指针成为可能,不允许一般的复制构造,这会造成严重破坏。
std::auto_ptr
使用的解决方案是涉及一个具有隐式转换的中介指针载体类。这很复杂。我记得当我写一个(曾经被维基百科引用过)指针教程时,在 Visual C++ 的 std::auto_ptr
实现中遇到了大量的特性。
下面的代码,希望是有效的 C++03(使用 g++ -std=c++03
测试),而是基于程序员通过调用明确指示需要移动操作的位置as_movable
成员函数。它使用 volatile
作为一种标记,以确保当 as_movable
的结果用作构造函数参数时,只有移动构造函数才能适合。在 C++03 中使用 volatile
作为标签的想法,尽管是在完全不同的上下文中,曾经由 Andrei Alexandrescu 提出;可能是他之前的其他人,但据我记得他的用法是我第一次遇到这个想法。
放置分配和释放运算符operator new
和operator delete
是为异常安全 定义的。特别是,当相关类型的构造函数通过抛出指示失败时,此处定义的放置 operator delete
仅由 new
表达式隐式调用一个异常(exception)。然后在重新抛出异常之前使用此运算符释放内存。
#include <exception> // std::terminate
#include <new> // std::bad_alloc
#include <stddef.h> // size_t
#include <stdlib.h> // malloc, free, NULL
#define MY_NEW( type, args ) \
::new type args
#define MY_MALLOC( type, args ) \
::new( my::c_memory_management ) type args
namespace my {
struct C_memory_management {};
C_memory_management const c_memory_management = C_memory_management();
} // namespace my
void*
operator new( size_t const size, my::C_memory_management )
{
void* result = malloc( size );
if( not result ) { throw std::bad_alloc(); }
return result;
}
// This operator is (only) called automatically by a new-expression where the
// constructor for the type, throws. After the call the exception is re-thrown.
void operator delete( void* const p, my::C_memory_management )
{
free( p );
}
#ifdef SUPPORT_ARRAYS
void*
operator new[]( size_t const size, my::C_memory_management const cmm )
{
return operator new( size, cmm );
}
void operator delete[]( void* const p, my::C_memory_management const cmm )
{
operator delete( p, cmm );
}
#endif
namespace my {
template< class Referent >
struct Destruction_via_delete_
{
static void destroy( Referent const* p )
{
try
{
delete p;
}
catch( ... )
{
std::terminate();
}
}
};
template< class Referent >
struct Destruction_via_free_
{
static void destroy( Referent const* p )
{
try
{
p->~Referent();
}
catch( ... )
{
std::terminate();
}
::free( const_cast<Referent*>( p ) );
}
};
template< class Referent >
class Auto_ptr_
{
public:
typedef void Destruction_func( Referent const* );
private:
Auto_ptr_& operator=( Auto_ptr_ const& ); // No copy assignment.
Auto_ptr_( Auto_ptr_ const& ); // No COPYING via copy constructor.
// A non-const argument copy constructor, for moving, is defined below.
Referent* p_;
Destruction_func* destroy_func_;
static void dummy_destroy_func( Referent const* ) {}
public:
Auto_ptr_ volatile&
as_movable()
{ return const_cast<Auto_ptr_ volatile&>( *this ); }
Referent*
release()
{
Referent* result = p_;
p_ = NULL;
return p_;
}
Referent*
operator->() const
{ return p_; }
Referent&
operator*() const
{ return *p_; }
~Auto_ptr_()
{ destroy_func_( p_ ); }
Auto_ptr_()
: p_( NULL )
, destroy_func_( &dummy_destroy_func )
{}
explicit Auto_ptr_(
Referent* const p,
Destruction_func* const destroy_func = &Destruction_via_delete_<Referent>::destroy
)
: p_( p )
, destroy_func_( destroy_func )
{}
explicit Auto_ptr_(
C_memory_management, // tag
Referent* const p
)
: p_( p )
, destroy_func_( &Destruction_via_free_<Referent>::destroy )
{}
// A C++03 emulation of move constructor; allows return of lvalue.
Auto_ptr_( Auto_ptr_ volatile& other )
: p_( other.p_ )
, destroy_func_( other.destroy_func_ )
{
other.p_ = NULL;
other.destroy_func_ = &dummy_destroy_func;
}
};
} // namespace my
#include <stdio.h>
struct Blah
{
char const* hello() const { return "Hello from Blah-land! :)"; }
~Blah() { printf( "<destroy>\n" ); }
Blah() { printf( "<init>\n" ); }
};
my::Auto_ptr_< Blah >
foo()
{
using namespace my;
Auto_ptr_< Blah > p( c_memory_management, MY_MALLOC( Blah,() ) );
return p.as_movable();
}
void bar( my::Auto_ptr_<Blah> const p )
{
printf( "%s\n", p->hello() );
}
int main()
{
my::Auto_ptr_<Blah> p = foo().as_movable();
printf( "Calling bar()...\n" );
bar( p.as_movable() );
printf( "Returned from bar().\n" );
}
输出:
<init>Calling bar()...Hello from Blah-land! :)<destroy>Returned from bar().
免责声明:我没有为上面的代码编写任何单元测试,实际上唯一的测试就是上面显示的有效的测试。恕我直言,测试人们希望它适用的各种情况是在生产代码中使用它所必需的。
关于C++03 带 free() 的智能指针,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41570140/
运行 PostgreSQL(7.4 和 8.x),我认为这是可行的,但现在我遇到了错误。 我可以单独运行查询,它工作得很好,但如果我使用 UNION 或 UNION ALL,它会抛出错误。 这个错误:
我试图为我的应用程序创建一个导航,使用抽屉导航我的 fragment 之一(HomeFragment)有一个 ViewPager,可容纳 3 个 fragment (Bundy Clock、Annou
以我目前正在开发的应用为例: - 它有一个包含多个项目的抽屉导航;现在有两个项目让我感兴趣,我将它们称为 X 和 Y。 X 和 Y 都在单击时显示包含 x 元素或 y 元素列表的 fragment 选
我有一个形状为 (370,275,210) 的 NumPy 数组,我想将其重新整形为 (275,210,370)。我将如何在 Python 中实现这一点? 370是波段数,275是行数,210是图像包
我们如何与被子 UIViewController 阻止的父 UIViewController(具有按钮)交互。显然,触摸事件不会通过子 Nib 。 (启用用户交互) 注意:我正在加载默认和自定义 NI
我是 Jpa 新手,我想执行过程 我的代码如下 private static final String PERSISTENCE_UNIT_NAME = "todos"; private static
与安装了 LAMP 的 GCE 相比,选择与 Google Cloud SQL 链接的 GCE 实例有哪些优势? 我确定 GCE 是可扩展的,但是安装在其上的 mysql 数据库的可扩展性如何? 使用
这个问题在这里已经有了答案: Value receiver vs. pointer receiver (3 个答案) 关闭 3 年前。 我刚接触 golang。只是想了解为 Calc 类型声明的两种
我不小心按了一个快捷键,一个非常漂亮的断线出现在日期上。 有点像 # 23 Jun 2010 -------------------- 有人知道有问题的快捷方式吗?? (我在 mac 上工作!) 在
我正在Scala中编写正则表达式 val regex = "^foo.*$".r 这很好,但是如果我想做 var x = "foo" val regex = s"""^$x.*$""".r 现在我们有
以下 XML 文档在技术上是否相同? James Dean 19 和: James Dean 19 最佳答案 这两个文档在语义上是相同的。在 X
我在对数据帧列表运行稳健的线性回归模型(使用 MASS 库中的 rlm)时遇到问题。 可重现的示例: var1 <- c(1:100) var2 <- var1*var1 df1 <- data.f
好的,我有一个自定义数字键盘,可以在标签(numberField)中将数字显示为 0.00,现在我需要它显示 $0.00。 NSString *digit = sender.currentTitle;
在基于文档的应用程序中,使用 XIB 文件,创建新窗口时其行为是: 根据最后一个事件的位置进行定位和调整大小 window 。 如果最后一个事件窗口仍然可见,则新窗口 窗口应该是级联的,这样它就不会直
我想使用参数进行查询,如下所示: SELECT * FROM MATABLE WHERE MT_ID IN (368134, 181956) 所以我考虑一下 SELECT * FROM MATABLE
我遇到一些性能问题。 我有一个大约有 200 万行的表。 CREATE TABLE [dbo].[M8]( [M8_ID] [int] IDENTITY(1,1) NOT NULL,
我在 jquery 中的按键功能遇到问题。我不知道为什么按键功能不起作用。我已经使用了正确的 key 代码。在我的函数中有 2 个代码,其中包含 2 个事件键,按一个键表示 (+) 代码 107 和(
我想显示音频波形,我得到了此代码,它需要.raw音频输入并显示音频波形,但是当我放入.3gp,.mp3音频时,我得到白噪声,有人可以帮助我如何使其按需与.3gp一起使用使用.3gp音频运行它。 Inp
我无法让 stristr 函数返回真值,我相信这是因为我的搜索中有一个 $ 字符。 当我这样做时: var_dump($nopricecart); 完整的 $nopricecart 值是 $0 ,我得
如果我有这样的循环: for(int i=0;i O(n) 次。所以do some执行了O(n)次。如果做某事是线性时间,那么代码片段的复杂度是O(n^2)。 关于algorithm - 带 If 语
我是一名优秀的程序员,十分优秀!