相关疑难解决方法(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万
查看次数

pImpl成语是否真的在实践中使用?

我正在阅读Herb Sutter的"Exceptional C++"一书,在那本书中我学到了关于pImpl的习语.基本上,我们的想法是为a的private对象创建一个结构class并动态分配它们以减少编译时间(并且还以更好的方式隐藏私有实现).

例如:

class X
{
private:
  C c;
  D d;  
} ;
Run Code Online (Sandbox Code Playgroud)

可以改为:

class X
{
private:
  struct XImpl;
  XImpl* pImpl;       
};
Run Code Online (Sandbox Code Playgroud)

并且,在CPP中,定义:

struct X::XImpl
{
  C c;
  D d;
};
Run Code Online (Sandbox Code Playgroud)

这看起来很有趣,但我以前从未见过这种方法,既没有在我工作的公司,也没有在我看过源代码的开源项目中.所以,我想知道这种技术真的在实践中使用了吗?

我应该在任何地方使用它,还是谨慎使用?这种技术是否建议用于嵌入式系统(性能非常重要)?

c++ oop pimpl-idiom

157
推荐指数
7
解决办法
3万
查看次数

GotW#101"解决方案"实际上解决了什么问题吗?

首先阅读Herb's Sutters GotW关于C++ 11中pimpl的帖子:

我在理解GotW#101中提出的解决方案时遇到了一些麻烦.据我所知,在GotW#100中辛苦解决的所有问题都复仇了:

  • pimpl成员是外的线的模板,并且定义并不在使用点可见(在class widget的类定义和隐式生成的特殊成员函数widget).也没有任何明确的实例化.这将导致链接期间未解决的外部错误.

  • widget::impl实例化定义的点上仍然是不完整的(我认为它实际上根本没有pimpl<widget::impl>::~pimpl()实例化,只是被引用).因此std::unique_ptr<widget::impl>::~unique_ptr()调用delete指向不完整类型的指针,如果widget::impl有一个非平凡的析构函数,则会产生未定义的行为.

请解释是什么迫使编译器在widget::impl完成的上下文中生成特殊成员.因为我看不出它是如何工作的.


如果GotW#101仍然需要widget::~widget()在实现文件中明确定义,哪里widget::impl完成,那么请解释"更健壮"的评论(@sehe在他的答案中引用).

我看的GotW#101的核心要求是,包装"消除样板的一些作品",这在我看来(基于该段的其余部分)来表示的widget::~widget()声明和定义.所以请不要依赖于你的答案,在GotW#101中,那已经消失了!


Herb,如果你停下来,请告诉我是否可以在这里剪切+粘贴解决方案代码以供参考.

c++ pimpl-idiom incomplete-type c++11 gotw

21
推荐指数
2
解决办法
1856
查看次数

为什么要将类放在实现文件中?

在查看一些代码时,我遇到了以下内容:

.h文件

class ExampleClass
{
public:
    // methods, etc
private:
    class AnotherExampleClass* ptrToClass;
}
Run Code Online (Sandbox Code Playgroud)

.cpp文件

class AnotherExampleClass
{
    // methods, etc
}

// AnotherExampleClass and ExampleClass implemented 
Run Code Online (Sandbox Code Playgroud)

在c ++中工作时,这是一种模式还是有益的?由于该类没有分成另一个文件,这个工作流程是否会促进更快的编译时间?

或者这只是这个开发者的风格?

c++ class

20
推荐指数
3
解决办法
1252
查看次数

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
查看次数

C++ 11:是否声明了默认的复制构造函数用户?

我想是的,但我正在寻找C++ 11语言律师来证实我的印象.下面的课是真的吗?

struct X{
X(){}
X(X const&)=default;
};
Run Code Online (Sandbox Code Playgroud)

将不会自动移动启用,即获取X(X&&)operator=(X&&),因为它的复制构造函数是"用户声明的",即使它看起来相当于

struct X{
};
Run Code Online (Sandbox Code Playgroud)

这将同时获得X(X const&)X(X&&)等,隐含申报和(平凡)上使用的定义.

c++ c++11

14
推荐指数
1
解决办法
2058
查看次数

PIMPL 习惯用法实际上可以使用 std::unique_ptr 工作吗?

我一直在尝试通过使用 unique_ptr 来实现 PIMPL 习惯用法。\n我从几篇文章中得到启发,这些文章总是强调相同的要点:仅在实现 PIMPL 的类的标头中声明析构函数,然后在您的 . .cpp 文件。否则,您将收到诸如“Incomplete type bla bla”之类的编译错误。

\n

好吧,我做了一个尊重这一点的小测试,但我仍然有“不完整类型”错误。代码就在下面,非常短。

\n

A.hpp:

\n
#pragma once\n#include <memory>\n\nclass A\n{\npublic:\n  A();\n  ~A();\nprivate:\n  class B;\n  std::unique_ptr<B> m_b = nullptr;\n};\n
Run Code Online (Sandbox Code Playgroud)\n

A.cpp:

\n
#include "A.hpp"\n\nclass A::B\n{\n\n};\n\nA::A()\n{\n\n}\n\nA::~A() // could be also \'= default\'\n{\n\n}\n
Run Code Online (Sandbox Code Playgroud)\n

主要.cpp:

\n
#include "A.hpp"\n\nint main()\n{\n  A a1;\n\n  return 0;\n}\n
Run Code Online (Sandbox Code Playgroud)\n

我用两种(快速和肮脏的)方式构建,从我的角度来看,结果非常令人惊讶。

\n

首先我在没有链接 A.cpp 的情况下构建

\n
g++ -c A.cpp\n
Run Code Online (Sandbox Code Playgroud)\n

到目前为止没有错误。

\n

然后,我编译了 A.cpp 和 main.cpp 以创建可执行文件

\n
g++ A.cpp main.cpp -o test\n
Run Code Online (Sandbox Code Playgroud)\n

这就是我遇到麻烦的地方。这里我得到了关于不完整类型的著名错误:

\n
In …
Run Code Online (Sandbox Code Playgroud)

c++ c++11 c++14

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