是否有一个标准指针类(或Boost),它是一个非共享指针,适用于不完整类型?我已经浏览了C++ 11标准和boost库,但找不到它,虽然它看起来像一个非常有用的类型.
例如,我希望能够使用智能指针创建不透明类型.
class A;
wrap_ptr<A> some_func();
void other_func( A const & );
Run Code Online (Sandbox Code Playgroud)
A是一种不透明的类型,可用于各种功能.上述接口的用户只有一个不完整的A定义,但应该能够删除/重置指针.我知道上面的内容可以用a来完成,shared_ptr但是在这个特定的代码中我不需要开销.unique_ptr具有正确的所有权语义,但不能使用不完整的类型.理论上,包装器应该只需要指向删除器的开销.
在C++ 11或boost库中是否有这样的类型?
注意:我知道我可以很容易地构建这种类型,但如果可能的话我更喜欢标准类型.它似乎应该是一个基本的智能指针类型.
更新:unique_ptr似乎不是一个好的选择.首先,语法开销会抵消.其次,我不相信它可以安全地与自定义删除器一起使用.我会检查它是如何工作的.
以下是代码的极简主义问题:
struct B {
B () = default;
//~B () {}; // error: use of deleted function ‘B& B::operator=(const B&)’
std::unique_ptr<int> m_pB = nullptr;
};
int main ()
{
std::vector<B> vB;
vB.erase(vB.begin());
}
Run Code Online (Sandbox Code Playgroud)
除非析构函数被取消注释,否则上面的代码编译得很好.根据我的要求,我需要有一个~B()明确定义的主体.
如何unique_ptr在同一个类中共存来定义析构函数体?
注意:尝试= default复制和移动构造函数的定义版本无济于事.在我的真实代码中,unique_ptr<int>是unique_ptr<forward_declared_class>.无法在SO中找到此问题,但我确信它必须存在.随意标记为傻瓜.
我读过有关不完整类型的unique_ptr和Checked Delete.但是当使用智能指针或至少是C++ 11的智能指针的一个子集时,检查 - 删除是否已过时?
请使用以下代码:
class A;
class B
{
public:
std::auto_ptr<A> autoPtr;
std::unique_ptr<A> uniquePtr;
std::shared_ptr<A> sharedPtr;
A* rawPtr;
B();
~B(){delete rawPtr;}
};
class A
{
public:
~A(){std::cout << "~A" << std::endl;}
};
B::B()
{
autoPtr = std::auto_ptr<A>(new A());
uniquePtr = std::unique_ptr<A>(new A());
sharedPtr = std::shared_ptr<A>(new A());
rawPtr = new A();
}
B b;
Run Code Online (Sandbox Code Playgroud)
当定义B的析构函数时,A的类型仍然不完整.据我所知[C++ 11标准@ [expr.delete]],删除原始指针是未定义的行为.在我的机器上,gcc 4.8显示了一些关于此的警告但是编译并且A的析构函数没有被正确调用.
但智能指针呢?正如我所读,unique_ptr和shared_ptr必须符合c ++ 11标准.但是两个链接文档都说明了auto_ptr不起作用.但至少用我的gcc 4.8也auto_ptr正确调用析构函数,没有任何警告.这仍然是未定义的行为,gcc是不是很好?
简而言之:根据C++ 11标准,四个成员变量中的哪一个可以保证使用它后来定义的析构函数来适当地破坏它们的A指针?
最后:如果我只使用unique_ptr和shared_ptr并且永远不会自己调用"删除",我是否安全并且永远不需要再考虑"已删除"?
库定义了不透明的数据类型:
\n\nstruct OpaqueStruct;\nRun Code Online (Sandbox Code Playgroud)\n\n并且客户端代码必须获取并释放OpaqueStruct*. 我可以访问库源。
不幸的是,既不能存储该指针shared_ptr,也unique_ptr不能存储该指针,从而出现错误: invalid application of \xe2\x80\x98sizeof\xe2\x80\x99 to incomplete type。
我能想到的最好的办法就是从这篇文章中借用finally守卫 。
\n\n如何将 RAII 用于不透明结构指针?
\n我有
template<typename T>
class queue
{
private:
struct node
{
T data;
std::unique_ptr<node> next; //compile error on incomplete type
node(T&& data_):
data(std::move(data_))
{}
};
std::unique_ptr<node> head;
node* tail;
public:
queue():
tail(nullptr)
{}
Run Code Online (Sandbox Code Playgroud)
我在 VS10 的标记行上收到编译错误。在这种情况下,我不应该被允许使用不完整的类型(实例化模板 - 构造函数 - 这里以 int 为例)?有解决办法吗?
编辑
singlethreadedqueue.h(62): error C2079: 'queue<T>::node::next' uses undefined class 'std::unique_ptr<_Ty>'
1> with
1> [
1> T=MyClass
1> ]
1> and
1> [
1> _Ty=queue<MyClass>::node
1> ]
1> c:\program files\microsoft visual studio 10.0\vc\include\memory(2161) : see reference to class template instantiation 'queue<T>::node' …Run Code Online (Sandbox Code Playgroud) 我已经读过了std :: unique_ptr <T>需要知道T的完整定义吗?和unique_ptr转发声明?,但我的问题更具体.
以下编译:
// Compile with $ g++ -std=c++11 -c <filename>
#include <memory>
class A; // fwd declaration
class AUser
{
AUser(); // defined elsewhere
~AUser(); // defined elsewhere
std::unique_ptr<A> m_a;
};
Run Code Online (Sandbox Code Playgroud)
以下不是:
// Compile with $ g++ -std=c++11 -c <filename>
#include <memory>
class A; // fwd declaration
class AUser
{
AUser(); // defined elsewhere
~AUser(); // defined elsewhere
std::unique_ptr<A> m_a{nullptr};
};
Run Code Online (Sandbox Code Playgroud)
错误
$ g++ -std=c++11 -c fwd_decl_u_ptr.cpp
In file included from /usr/include/c++/4.7/memory:86:0,
from …Run Code Online (Sandbox Code Playgroud) 如果我有一个班级'酒吧':
// bar.h
class Bar
{
public:
Bar() { }
};
Run Code Online (Sandbox Code Playgroud)
我转发声明在另一个类'Foo'中使用std :: unique_ptr:
// foo.h
#include <memory>
class Bar;
class Foo
{
public:
Foo();
private:
std::unique_ptr<Bar> bar_;
};
Run Code Online (Sandbox Code Playgroud)
我将其定义包含在Foo的实现文件中:
// foo.cpp
#include "foo.h"
#include "bar.h"
Foo::Foo()
: bar_(new Bar)
{ }
Run Code Online (Sandbox Code Playgroud)
我得到编译时错误"'sizeof'的无效应用程序到一个不完整的类型'Bar'".
我从这里和这里理解为了解决这个问题,我可以在foo.h中声明Foo的析构函数并将其空定义移动到foo.cpp.我不明白的是,为什么要修复它.我读到std :: unique_ptr有时需要知道其类型的完整定义.如果我必须从bar.h包含Bar以便unique_ptr看到它的定义,那对我来说是有意义的.但是Foo的析构函数与Bar的可见性有什么关系?为什么在foo.h中声明~Foo()并在foo.cpp中定义它会使错误无效?
我不明白为什么我得到这个编译错误:
Run Code Online (Sandbox Code Playgroud)error C2027: use of undefined type 'GameState' note: see declaration of 'GameState' error C2338: can't delete an incomplete type warning C4150: deletion of pointer to incomplete type 'GameState'; no destructor called
这是相关代码:
#pragma once
#include <SFML\Graphics.hpp>
#include "SpawnManager.h"
#include "Resource.h"
#include <stack>
#include <memory>
class GameState;
class Controller
{
public:
Controller();
void run();
void setPlayerScore(unsigned score);
sf::RenderWindow& getWindow() { return m_window; }
void addState(const States& state);
void changeState(const States& state);
GameState* getState() const;
void popState();
void add_state(const States& type, …Run Code Online (Sandbox Code Playgroud) #include <memory>
class Data;
std::unique_ptr<Data> p;
//class Data{}; // not working without this
int main(){}
Run Code Online (Sandbox Code Playgroud)
使用g ++ - 5编译此代码会出现这样的错误:
将'sizeof'无效应用于不完整类型'数据'
有人可以解释为什么我取消注释第四行编译会成功吗?据我所知,在第3行编译器没有关于类型数据的完整信息.我们这行只有前瞻性声明.真实声明发生在第4行.
来自std::unique_ptr 需要知道 T 的完整定义吗?,我知道如果一个类A有一个成员unique_ptr<T>,那么T在析构函数中应该是一个完整的类型~A()。但是,我遇到了一种情况,构造函数A()也需要完整的类型T,请参见下面的代码:
// a.h -------------------------------\n#pragma once\n#include <memory>\nstruct B;\nstruct A {\n A(); // <---\n ~A();\n std::unique_ptr<B> ptr;\n};\n\n// a.cpp -------------------------------\n#include "a.h"\nstruct B {};\nA::A() = default; // <---\nA::~A() = default;\n\n// main.cpp -------------------------------\n#include "a.h"\nint main() {A a;}\nRun Code Online (Sandbox Code Playgroud)\n如果构造函数的定义A::A()被移动到头文件中a.h,编译器将会报错error: invalid application of \xe2\x80\x98sizeof\xe2\x80\x99 to incomplete type \xe2\x80\x98B\xe2\x80\x99。为什么会发生这种情况?有这方面的参考资料吗?
顺便说一句,我在 Ubuntu 18.04 上使用 gcc-7.5.0,启用了 c++17。
\n在评论中编辑@463035818_is_not_a_number。完整的错误信息是:
\n[1/2] Building CXX …Run Code Online (Sandbox Code Playgroud) c++ ×10
c++11 ×7
unique-ptr ×5
destructor ×2
boost ×1
c++14 ×1
oop ×1
shared-ptr ×1
std ×1
stl ×1
templates ×1