相关疑难解决方法(0)

是否需要std :: unique_ptr <T>才能知道T的完整定义?

我在头文件中有一些代码如下:

#include <memory>

class Thing;

class MyClass
{
    std::unique_ptr< Thing > my_thing;
};
Run Code Online (Sandbox Code Playgroud)

如果我有一个CPP这个头不包含的Thing类型定义,那么这并不在VS2010 SP1的编译:

1> C:\ Program Files(x86)\ Microsoft Visual Studio 10.0\VC\include\memory(2067):错误C2027:使用未定义类型'Thing'

替换std::unique_ptrstd::shared_ptr和编译.

所以,我猜这是当前VS2010 std::unique_ptr的实现,需要完整的定义,而且完全依赖于实现.

或者是吗?它的标准要求中是否有某些东西使得std::unique_ptr实施只能使用前向声明?感觉很奇怪,因为它应该只有一个指针Thing,不应该吗?

c++ stl visual-studio-2010 unique-ptr c++11

236
推荐指数
5
解决办法
4万
查看次数

不能使用std :: unique_ptr <T>,T是前向声明

首先,我知道unique_ptr <>和转发声明的一般问题,如使用unique_ptr的转发声明?.

考虑这三个文件:

#include <memory>
#include <vector>

class B;

class A
{
public:
    ~A();

private:
    std::unique_ptr<B> m_tilesets;
};
Run Code Online (Sandbox Code Playgroud)

C.cpp

#include "A.h"

class B {

};

A::~A() {

}
Run Code Online (Sandbox Code Playgroud)

main.cpp中

#include <memory>

#include "A.h"

int main() {
    std::unique_ptr<A> m_result(new A());
}
Run Code Online (Sandbox Code Playgroud)

发出会g++ -std=c++11 main.cpp C.cpp产生以下错误:

In file included from /usr/include/c++/4.8/memory:81:0,
                 from main.cpp:1:
/usr/include/c++/4.8/bits/unique_ptr.h: In instantiation of ‘void std::default_delete<_Tp>::operator()(_Tp*) const [with _Tp = B]’:
/usr/include/c++/4.8/bits/unique_ptr.h:184:16:   required from ‘std::unique_ptr<_Tp, _Dp>::~unique_ptr() [with _Tp = B; _Dp = std::default_delete<B>]’
A.h:6:7: …
Run Code Online (Sandbox Code Playgroud)

c++ forward-declaration unique-ptr c++11

17
推荐指数
2
解决办法
6533
查看次数

unique_ptr,pimpl/forward声明和完整定义

我已经在这里这里检查了问题,但仍然无法弄清楚出了什么问题.

这是调用代码:

#include "lib.h"

using namespace lib;

int
main(const int argc, const char *argv[]) 
{
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

这是lib代码:

#ifndef lib_h
#define lib_h

#include <string>
#include <vector>
#include <memory>

namespace lib
{

class Foo_impl;

class Foo
{
    public:
        Foo();
        ~Foo();

    private:
        Foo(const Foo&);
        Foo& operator=(const Foo&);

        std::unique_ptr<Foo_impl> m_impl = nullptr;

        friend class Foo_impl;
};

} // namespace

#endif
Run Code Online (Sandbox Code Playgroud)

clang ++给了我这个错误:

将'sizeof'无效应用于不完整类型'lib :: Foo_impl'
注意:在成员函数'std :: default_delete :: operator()'的实例化中请求

你可以看到我已经特别声明了Foo析构函数.我还缺少什么?

c++ language-lawyer c++11

15
推荐指数
2
解决办法
2900
查看次数

"使用undefined类型"与unique_ptr转发声明的类和默认的移动构造函数/赋值

在下面的代码中,是避免编译错误并在A.cpp中手动实现移动构造函数/赋值的Bh的唯一方法吗?

// A.h
#include <memory>
class B; // implementation somewhere in B.h/B.cpp
class A
{
public:
    A() = default;
    ~A() = default;
    A(const A&) = delete;
    A& operator=(const A&) = delete;
    A(A&&) = default;
    A& operator=(A&&) = default;

private:
    std::unique_ptr<B> m_b;
};
Run Code Online (Sandbox Code Playgroud)

Visual Studio 2015提供了"错误C2027:使用未定义类型",因为std :: unique_ptr的移动构造函数/赋值运算符调用m_b上的删除器(试图调用B的析构函数),这在此时显然是未知的.

c++ c++11

7
推荐指数
1
解决办法
1369
查看次数

unique_ptr实现中可能存在的错误

我试图使用带有前向声明的unique_ptr类成员.众多消息来源称例如使用unique_ptr进行前向声明?声明非内联析构函数应该足够了,但在VS2013和GCC 5.3.1中似乎不是这种情况.我没有测试其他编译器.

例:

#include <memory>

class B;

class A { 
public:
    //A();
    ~A();
private:
    std::unique_ptr<B> b;
};

//class B { };

int main() {
    A a;
}
Run Code Online (Sandbox Code Playgroud)

我只能在取消注释ctor声明或类B声明后才能编译此代码.否则在VS2013上我收到错误

error C2338: can't delete an incomplete type
Run Code Online (Sandbox Code Playgroud)

关于GCC错误:

In file included from /usr/local/include/c++/5.3.0/memory:81:0,
                 from main.cpp:1:
/usr/local/include/c++/5.3.0/bits/unique_ptr.h: In instantiation of 'void std::default_delete<_Tp>::operator()(_Tp*) const [with _Tp = B]':
/usr/local/include/c++/5.3.0/bits/unique_ptr.h:236:17:   required from 'std::unique_ptr<_Tp, _Dp>::~unique_ptr() [with _Tp = B; _Dp = std::default_delete<B>]'
main.cpp:5:7:   required from here
/usr/local/include/c++/5.3.0/bits/unique_ptr.h:74:22: error: invalid application of 'sizeof' …
Run Code Online (Sandbox Code Playgroud)

c++ unique-ptr c++11

6
推荐指数
1
解决办法
1204
查看次数

前向声明,unique_ptr和类内初始化器

我已经读过了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)

c++ forward-declaration unique-ptr in-class-initialization

5
推荐指数
1
解决办法
2118
查看次数

使用智能指针和继承构造函数的前向声明

根据这个问题,如果所有构造函数和析构函数都不是内联的(则需要完全定义的类型),则可以转发声明智能指针。当未提供析构函数时,编译器将声明一个析构函数并提供内联定义,该定义随后要求标头中完全已知智能指针中的类型。这同样适用于默认构造函数。

然而,我发现它也适用于继承的构造函数,这对我来说有点令人困惑。考虑:

class Base
{
public:
    Base(); //defined in cpp
};

class SomeClass;

class Derived : public Base
{
    using Base::Base;
    ~Derived(); //defined in cpp

    std::unique_ptr<SomeClass> ptr;
};
Run Code Online (Sandbox Code Playgroud)

Derived除非显式声明构造函数并仅在源文件中定义,否则不会编译。为什么?构造函数Base不是内联的,据我所知,using 指令应该以与其他成员类似的方式导致构造函数的“继承”。或者编译器是否将其解释为“为我声明与中相同的构造函数Base并内联定义它们”?

c++ constructor smart-pointers forward-declaration c++11

2
推荐指数
1
解决办法
4676
查看次数

什么时候在C ++中发生不完整的类型错误

谁能告诉我C ++编译器何时引发“不完整的类型错误”?

注意:我故意将这个问题留给了一些开放的答案,以便我自己调试代码。

c++ incomplete-type

2
推荐指数
1
解决办法
3520
查看次数

使用 pimpl 习惯用法时 C++ 中的构造函数和析构函数

我来自 Java,它有一种不同的方式来处理私有内容,并且必须隐藏类实现,并且它还有一个垃圾收集器,这意味着不需要析构函数。

我学习了如何在 C++ 中实现类的基础知识,但在使用 pimpl 习惯用法时,我需要更好地理解如何实现类,特别是构造函数和析构函数。

.hpp 文件:

class MyClass{
public:
  MyClass();
  MyClass(std::vector<int>& arr);
  ~MyClass();

 
private:
  struct Impl;
  Impl* pimpl;
};
Run Code Online (Sandbox Code Playgroud)

.cpp 文件:

#include "MyClass.hpp"
using namespace std;


struct MyClass::Impl{
  vector<int> arr;
  int var;
};
Run Code Online (Sandbox Code Playgroud)

我使用 pimpl 惯用法编写了我需要处理的类的示例代码(这意味着我无法更改 pimpl 惯用法的使用方式),我正在寻找这些问题的答案:

  • 如何实现构造函数来创建 MyClass 的空实例?
MyClass::MyClass(){}
Run Code Online (Sandbox Code Playgroud)
  • 如何实现构造函数来使用这些参数创建 MyClass 实例?
MyClass::MyClass(vector<int>& arr,int var){}
Run Code Online (Sandbox Code Playgroud)
  • 我如何实现析构函数?
MyClass::~MyClass(){}
Run Code Online (Sandbox Code Playgroud)

编辑:

我会怎么做:

MyClass::MyClass(): pimpl(new Impl) {}

MyClass::MyClass(vector<int>& arr,int var): pimpl(new Impl) {
  pimpl->arr=arr;
  pimpl->var=var;
}

MyClass::~MyClass(){
  delete pimpl;
}

Run Code Online (Sandbox Code Playgroud)

c++ pimpl-idiom

2
推荐指数
1
解决办法
631
查看次数