在我的工作场所,我们有这样的约定:几乎每个类(除了极少数例外)都使用unique_ptrs、原始指针或引用作为成员变量来实现。
这是因为编译时间的原因:通过这种方式,您只需要在头文件中对类进行前向声明,并且只需要在 cpp 中包含该文件。此外,如果您更改包含的类的 .h 或 .cpp,unique_ptr则不需要重新编译。
我认为这种模式至少有以下缺点:
std::vector<std::unique_ptr<MyClass>>而不是更简单的std::vector<MyPimplClass>.因此,我想到建议对作为指针包含的类使用 pImpl 习惯用法,而不是在任何地方使用指针。通过这种方式,我认为我们可以两全其美:
A::A(const A& rhs) : pImpl(std::make_unique<Impl>(*rhs.pImpl)) {}
A& A::operator=(const A& rhs) {
*pImpl = *rhs.pImpl;
return *this;
}
Run Code Online (Sandbox Code Playgroud)
在这一点上,我与我的同事进行了讨论,他们认为 pImpl 并不比在任何地方使用指针更好,原因如下:
现在我有点困惑。我认为我们的实际约定并不比 pImpl 好,但我无法争论为什么。
所以我有一些问题:
编辑:我正在添加一些示例来阐明这两种方法。
unique_ptr为成员:// B.h
#pragma once
class B {
int i = 42;
public:
void print();
}; …Run Code Online (Sandbox Code Playgroud) 鉴于以下代码:
#include <iostream>
#include <memory>
struct A {};
struct B : public A {};
std::pair<bool, std::unique_ptr<B>> GetBoolAndB() {
return { true, std::make_unique<B>() };
}
std::unique_ptr<A> GetA1() {
auto[a, b] = GetBoolAndB();
return b;
}
std::unique_ptr<A> GetA2() {
auto [a, b] = GetBoolAndB();
return std::move(b);
}
Run Code Online (Sandbox Code Playgroud)
GetA1 不编译,出现此错误:
C2440: 'return': cannot convert from 'std::unique_ptr<B,std::default_delete<_Ty>>' to 'std::unique_ptr<A,std::default_delete<_Ty>>'
虽然GetA2编译没有错误。
我不明白为什么我需要调用std::move才能使函数工作。
编辑
只是为了澄清,正如 DanielLangr 在评论中指出的那样,我怀疑的是
std::unique_ptr<A> GetA3() {
std::unique_ptr<B> b2;
return b2;
}
Run Code Online (Sandbox Code Playgroud)
无需std::move.
现在我明白,在GetA1and 的情况下 …
我正在尝试从 移植boost::filesystem到std::filesystem。在这个过程中,我遇到了一些代码,其中boost和std似乎以不同的方式表现。
以下代码显示了该行为:
#include <iostream>
#include <filesystem>
#include <boost/filesystem.hpp>
template<typename T>
void TestOperatorSlash()
{
const std::string foo = "Foo";
const std::string bar = "Bar";
const T start = "\\";
std::string sep;
sep += T::preferred_separator;
const auto output = start / (foo + bar) / sep;
std::cout << output << '\n';
}
int main(int argc, char** argv)
{
TestOperatorSlash<std::filesystem::path>();
TestOperatorSlash<boost::filesystem::path>();
}
Run Code Online (Sandbox Code Playgroud)
该代码给出输出:
"\\"
"\FooBar\"
Run Code Online (Sandbox Code Playgroud)
我的预期行为是boost,我不明白 会发生什么std::filesystem。
为什么我得到"\\"?为什么和 …
我遇到了无法解释的包含顺序问题。我将向您展示一个包含四个文件的最小示例:
// A.h
#pragma once
#include <functional>
struct A {};
namespace std {
template<>
class hash<A> {
public:
size_t operator()(const A&) const {
return 0;
};
};
}
// B.h
#pragma once
#include <unordered_map>
struct A;
struct B {
const std::unordered_map<A, int>& GetMap() const;
};
// B.cpp
#include "B.h"
#include "A.h"
const std::unordered_map<A, int>& B::GetMap() const {
static std::unordered_map<A, int> m;
return m;
}
// main.cpp
#include "A.h" // To be included AFTER B.h
#include "B.h"
int main() {
B …Run Code Online (Sandbox Code Playgroud) 我有以下代码,我正在使用 MSVC:
template <typename T>
void CanMock() {
class SimpleType {};
static_assert(sizeof(void(SimpleType::*)()) == sizeof(void(T::*)()),
"Can't mock a type with multiple inheritance or with "
"non-polymorphic base class");
}
int main() {
class base {};
class derived : public base {};
class derivedVirtual : virtual public base {};
CanMock<derived>();
CanMock<derivedVirtual>();
}
Run Code Online (Sandbox Code Playgroud)
in调用时通过,但调用时static_assert失败。CanMockderivedderivedVirtual
据我了解,断言尝试将 a 的类函数指针的大小SimpleType与 的类函数指针的大小进行比较derivedVirtual,
现在我的问题是:
derivedVirtual应该增加,因为其中存储了 vtable 指针(对吗?),但是为什么derivedVirtual继承 with 时类函数指针的大小会增加virtual?c++ ×5
c++17 ×2
boost ×1
cl ×1
compile-time ×1
fakeit ×1
filesystems ×1
include ×1
inheritance ×1
mocking ×1
pimpl ×1
std ×1
unique-ptr ×1
virtual ×1