有人可以向我解释为什么这段代码只打印"42"而不是"创建\n42"?
#include <iostream>
#include <string>
#include <memory>
using namespace std;
class MyClass
{
public:
MyClass() {cout<<"created"<<endl;};
int solution() {return 42;}
virtual ~MyClass() {};
};
int main(int argc, char *argv[])
{
auto_ptr<MyClass> ptr;
cout<<ptr->solution()<<endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
顺便说一句,我在解决方案中使用不同的值尝试了这个代码,我总是得到"正确"的值,因此它似乎不是一个随机的幸运值.
我需要在我的代码中从shared_ptr获取auto_ptr.我可以做反向操作 - 将auto_ptr转换为shared_ptr,因为shared_ptr有这样的构造函数:
template<class Y> explicit shared_ptr(std::auto_ptr<Y> & r);
Run Code Online (Sandbox Code Playgroud)
我可以将shared_ptr转换为auto_ptr吗?或者设计不可能?
假设我已经分配了堆A*,我希望将其作为参数传递给boost::bind.
boost::bind保存以供稍后处理某些STL的容器boost::functions.
我想确保A*在销毁STL容器时销毁.
示范:
A* pA = new A();
// some time later
container.push_back(boost::bind(&SomeClass::HandleA, this, pA);
// some time later
container is destroyed => pA is destroyed too
Run Code Online (Sandbox Code Playgroud)
怎么做到呢?
编辑
也许我想要的不是那么现实.
我有原始指针和函数接收原始指针.通过boost :: bind延迟调用.此时我想要自动内存管理,以防boost :: bind想要执行.我很懒,所以我想使用"准备好"的智能指针解决方案.
std :: auto_ptr看起来像个好人,但是......
auto_ptr<A> pAutoA(pA);
container.push_back(boost::bind(&SomeClass::HandleA, this, pAutoA);
Run Code Online (Sandbox Code Playgroud)
不编译(见这里)
auto_ptr<A> pAutoA(pA);
container.push_back(boost::bind(&SomeClass::HandleA, this, boost::ref(pAutoA));
Run Code Online (Sandbox Code Playgroud)
pAutoA被破坏,删除了底层的pA.
编辑02
在上面提到的容器中,我将需要使用不同的参数存储misc"回调".其中一些是对象的原始指针.由于代码是旧的,我并不总是可以改变它.
编写自己的包装器来存储容器中的回调是最后的手段(可能是唯一的),因此是赏金.
我遇到了几个问题,其答案表明使用T*绝不是最好的主意.
虽然我已经大量使用RIIC,但我的代码中有一个特殊点,我使用T*.阅读几个自动指针,我找不到一个我会说我有使用它的明显优势.
我的情景:
class MyClass
{
...
// This map is huge and only used by MyClass and
// and several objects that are only used by MyClass as well.
HashMap<string, Id> _hugeIdMap;
...
void doSomething()
{
MyMapper mapper;
// Here is what I pass. The reason I can't pass a const-ref is
// that the mapper may possibly assign new IDs for keys not yet in the map.
mapper.setIdMap(&_hugeIdMap);
mapper.map(...);
}
}
Run Code Online (Sandbox Code Playgroud)
MyMapper现在有一个HashMap<...>*成员,根据对无关问题的问题的高度投票答案 - 从来不是一个好主意(在实例之前,映射器将超出范围MyClass …
我了解到STL可以禁止程序员将auto_ptr放入容器中.例如,以下代码无法编译:
auto_ptr<int> a(new int(10));
vector<auto_ptr<int> > v;
v.push_back(a);
Run Code Online (Sandbox Code Playgroud)
auto_ptr有复制构造函数,为什么这段代码甚至可以编译?
请考虑以下代码:
std::auto_ptr<std::string> p;
if (p.get() == 0) {
...
}
Run Code Online (Sandbox Code Playgroud)
get()成员函数是否是用于检查p尚未初始化的标准且可靠的方法?它是否总是返回0,无论平台,编译器,编译器的优化标志等如何?
除了使用auto_ptrs的所有已知好处之外,auto_ptr是什么"最差实践"?
创建auto_ptrs的STL限制器.auto_ptrs不符合'CopyConstructable'要求.另见Scott Meyer的"Effective STL",第8项.
创建数组的auto_ptrs在销毁时,auto_ptr的析构函数使用'delete'(并且永远不会'delete []')来销毁拥有的对象,因此这段代码会产生未定义的行为:auto_ptr api(new int [42]);
不使用auto_ptr成员在类中处理copy-ctor和op =.有人可能天真地认为通过使用auto_ptr成员,不需要为类实现复制构造函数/赋值运算符.然而,即使是一个auto_ptr成员'毒化'一个类(即违反'CopyConstructable'和'Assignable'要求).在复制/分配操作期间,这些类的对象将被部分损坏.
还有更多的auto_ptr陷阱吗?
偶尔,对于稍纵即逝的时刻,我认为auto_ptr很酷.但大多数时候我都认识到有更简单的技术可以使它变得无关紧要.例如,如果我想自动释放一个对象,即使抛出异常,我也可以新建对象并分配给auto_ptr.很酷!但我可以更容易地创建我的对象作为局部变量,并让堆栈处理它(呃!).
因此,当我发现谷歌C++编码标准禁止使用auto_ptr 时,我并不感到惊讶.谷歌声明应该使用scoped_ptr(如果需要智能指针).
我想知道,与我的经验相反,是否有人能够给出auto_ptr何时使用的最佳或最简单的理由.如果没有,那么我想我会禁止自己使用它(跟谷歌领先).
更新:对于那些表示担忧的人,不,我没有采用谷歌标准.例如,针对谷歌建议,我同意应该激活异常处理.我也喜欢使用预处理器宏,例如我制作的可打印枚举.这只是让我感到震惊的auto_ptr主题.
update2:事实证明我的回答来自下面的两个响应者,以及维基百科的一个注释.首先,Herb Sutter确实展示了一种有效的用途(源 - 汇成语和与生命有关的对象组成).其次,有些商店不提供或禁止TR1和boost,只允许使用C++ 03.第三,根据维基百科,C++ 0x规范正在弃用auto_ptr并将其替换为unique_ptr.所以我的答案是:如果我可以使用unique_ptr(在所有考虑的平台上),否则使用auto_ptr来表示Sutter描述的情况.
请考虑以下代码:
#include<memory>
struct A {
std::auto_ptr<int> i;
};
A F() {
A a;
return a;
}
int main(int argc, char **argv) {
A a = F();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
编译时我收到编译错误,(见这里):
error: no matching function for call to ‘A::A(A)’
A a = F();
^
Run Code Online (Sandbox Code Playgroud)
根据我的理解,A::A(A)甚至不允许存在,那么编译器为什么要求它呢?其次,为什么不使用RVO?
如果是因为std::auto_ptr无法从函数返回,为什么以下编译运行?
#include<memory>
std::auto_ptr<int> F() {
std::auto_ptr<int> ap;
return ap;
}
int main(int argc, char **argv) {
std::auto_ptr<int> ap = F();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我不能在我目前的工作中使用C++ 11,因此使用auto_ptr.
我收到编译错误,发现有趣的东西.由于某种原因unique_ptr有一个超载auto_ptr,但我认为auto_ptr已被弃用:
/usr/local/include/c++/4.9.0/bits/unique_ptr.h:228:2:
note:template<class _Up, class>
std::unique_ptr<_Tp, _Dp>::unique_ptr(std::auto_ptr<_Up>&&)
unique_ptr(auto_ptr<_Up>&& __u) noexcept;
/usr/local/include/c++/4.9.0/bits/unique_ptr.h:228:2:
note: template argument deduction/substitution failed:
main.cpp:41:67: note: mismatched types 'std::auto_ptr<T>' and 'char*'
Run Code Online (Sandbox Code Playgroud)
这是因为与使用的代码向后兼容auto_ptr吗?
auto-ptr ×10
c++ ×10
boost-bind ×1
c++03 ×1
c++11 ×1
coding-style ×1
gcc ×1
pointers ×1
shared-ptr ×1
stl ×1
unique-ptr ×1