如何阻止使用 std::make_shared<T>
how to block usage of std::make_shared<T>
我知道我可以通过将 class 的 operator new
设为私有来防止自定义 class 及其后代的普通堆分配,但是有什么方法可以防止用户在自定义 class(或其后代)上调用 std::make_shared
的库? Apparently,只是在 class 中将 operator new
设为私有并不能阻止它。
请注意,我不想完全阻止以任何方式创建共享指针,因为我仍打算通过调用静态方法为我的自定义 class 生成 std::shared_ptr
生成器方法,但我仍然想阻止其他人尝试直接在我的 class 上调用 std::make_shared
。
编辑:
为了解决下面的问题,我的最终目标是一种灵活且可重用的机制,用于从原始指针中提取 shared_ptr。 std::enable_shared_from_this
遗憾的是在继承尤其是多重继承方面不是很友好。
此外,因为我打算将其用作模板 class 使用 CRTP,这会使 child class 的事情变得有些复杂T 需要显式地使模板化 parent class 它继承自朋友,以便它可以访问其他私有构造函数。
这不是特定于 std::shared_ptr
,但您可以将构造函数设为私有,这样可以强制 class 的所有实例从您的静态方法生成。
#include <iostream>
#include <memory>
class Foo {
private:
Foo() = default;
public:
static std::shared_ptr<Foo> make() {
return std::shared_ptr<Foo>(new Foo);
}
};
int main() {
//Foo f1;
//auto f2 = std::make_shared<Foo>();
//above does not work since the constructor is private
auto h = Foo::make();
}
您还可以使用重复数据删除器建议并使用私钥使构造函数在 class 之外无法访问。
#include <iostream>
#include <memory>
class Foo {
private:
struct FooKey {};
public:
Foo(FooKey) {};
static std::shared_ptr<Foo> make() {
return std::make_shared<Foo>(FooKey{});
}
};
int main() {
//Foo f1{Foo::FooKey{}};
//auto f2 = std::make_shared<Foo>(Foo::FooKey{});
//above does not work since Foo::FooKey is private
auto h = Foo::make();
}
阻止类型T
的用户堆分配实际上不是您可以在C++ 中执行的操作。至少,只要他们可以创建 T
s。即使您设法禁止 make_shared<T>
,您的用户仍然可以这样做:
unique_ptr opt = new optional<T>;
opt->emplace(...);
*opt
里面的T
肯定在堆上。任何数量的其他类似体操都可以达到相同的效果。您甚至可以使用 in_place
参数调用 make_shared<optional<T>>
。
只要 T
具有可公开访问的构造函数,或者存在任何可公开访问的构造 T
且 return 是它的纯右值的方法,用户就可以找到存储的方法T
在堆上。
所以防止这种情况的唯一方法是将所有构造函数设为私有(无论是直接使用 private
还是 private
密钥类型或您想要的任何其他机制)并且只提供可公开访问的return shared_ptr<T>
s.
的函数
除了宏之外,没有任何 C++ 机制可以使类型以这种方式工作。对于您希望以这种方式工作的每种类型,必须单独完成。
以上回答是解决问题的较好方法。但是,如果您不想让 make_shared 创建您的 class 的新实例,也许这会有所帮助。
#include <iostream>
#include <memory>
using namespace std;
class A {
private:
void * operator new(size_t size) {}
};
template<> shared_ptr<A> make_shared() {
cout << "this was called.\n";
return nullptr;
}
int main() {
A a;
shared_ptr<A> p = make_shared<A>(a);
shared_ptr<A> q = make_shared<A>();
cout << "p: " << p << endl;
cout << "q: " << q << endl;
return 0;
}
'p' 获取对象地址而 'q' 没有。
注意:编译器中需要 -fpermissive 选项。
我知道我可以通过将 class 的 operator new
设为私有来防止自定义 class 及其后代的普通堆分配,但是有什么方法可以防止用户在自定义 class(或其后代)上调用 std::make_shared
的库? Apparently,只是在 class 中将 operator new
设为私有并不能阻止它。
请注意,我不想完全阻止以任何方式创建共享指针,因为我仍打算通过调用静态方法为我的自定义 class 生成 std::shared_ptr
生成器方法,但我仍然想阻止其他人尝试直接在我的 class 上调用 std::make_shared
。
编辑:
为了解决下面的问题,我的最终目标是一种灵活且可重用的机制,用于从原始指针中提取 shared_ptr。 std::enable_shared_from_this
遗憾的是在继承尤其是多重继承方面不是很友好。
此外,因为我打算将其用作模板 class 使用 CRTP,这会使 child class 的事情变得有些复杂T 需要显式地使模板化 parent class 它继承自朋友,以便它可以访问其他私有构造函数。
这不是特定于 std::shared_ptr
,但您可以将构造函数设为私有,这样可以强制 class 的所有实例从您的静态方法生成。
#include <iostream>
#include <memory>
class Foo {
private:
Foo() = default;
public:
static std::shared_ptr<Foo> make() {
return std::shared_ptr<Foo>(new Foo);
}
};
int main() {
//Foo f1;
//auto f2 = std::make_shared<Foo>();
//above does not work since the constructor is private
auto h = Foo::make();
}
您还可以使用重复数据删除器建议并使用私钥使构造函数在 class 之外无法访问。
#include <iostream>
#include <memory>
class Foo {
private:
struct FooKey {};
public:
Foo(FooKey) {};
static std::shared_ptr<Foo> make() {
return std::make_shared<Foo>(FooKey{});
}
};
int main() {
//Foo f1{Foo::FooKey{}};
//auto f2 = std::make_shared<Foo>(Foo::FooKey{});
//above does not work since Foo::FooKey is private
auto h = Foo::make();
}
阻止类型T
的用户堆分配实际上不是您可以在C++ 中执行的操作。至少,只要他们可以创建 T
s。即使您设法禁止 make_shared<T>
,您的用户仍然可以这样做:
unique_ptr opt = new optional<T>;
opt->emplace(...);
*opt
里面的T
肯定在堆上。任何数量的其他类似体操都可以达到相同的效果。您甚至可以使用 in_place
参数调用 make_shared<optional<T>>
。
只要 T
具有可公开访问的构造函数,或者存在任何可公开访问的构造 T
且 return 是它的纯右值的方法,用户就可以找到存储的方法T
在堆上。
所以防止这种情况的唯一方法是将所有构造函数设为私有(无论是直接使用 private
还是 private
密钥类型或您想要的任何其他机制)并且只提供可公开访问的return shared_ptr<T>
s.
除了宏之外,没有任何 C++ 机制可以使类型以这种方式工作。对于您希望以这种方式工作的每种类型,必须单独完成。
以上回答是解决问题的较好方法。但是,如果您不想让 make_shared 创建您的 class 的新实例,也许这会有所帮助。
#include <iostream>
#include <memory>
using namespace std;
class A {
private:
void * operator new(size_t size) {}
};
template<> shared_ptr<A> make_shared() {
cout << "this was called.\n";
return nullptr;
}
int main() {
A a;
shared_ptr<A> p = make_shared<A>(a);
shared_ptr<A> q = make_shared<A>();
cout << "p: " << p << endl;
cout << "q: " << q << endl;
return 0;
}
'p' 获取对象地址而 'q' 没有。
注意:编译器中需要 -fpermissive 选项。