std::unique_ptr
有一个已删除的复制构造函数,这意味着如果您unique_ptr
的类中有一个Foo
作为数据成员,那么您必须编写自己的复制构造函数Foo
并手动深层复制该成员(即使编译器生成的复制构造函数对所有人都可以.其他成员).
为了能够以多态方式进行复制,clone()
可以使用方法模式.让我们假设我们的对象有一个像这样的克隆方法:
class Base {
virtual std::unique_ptr<Base> clone() = 0;
};
Run Code Online (Sandbox Code Playgroud)
Foo现在看起来像这样:
class Foo {
public:
...
Foo(Foo const& other)
: b(other.b->clone())
, // init 10 more members that could otherwise be auto-copied just fine
// with the automatically generated copy constructor
{}
...
private:
std::unique_ptr<Base> b;
//10 more data members
};
Run Code Online (Sandbox Code Playgroud)
现在,我找到了一种自动克隆的方法Foo::b
,通过编写一个包装器unique_ptr
来定义复制构造函数和通过调用赋值clone
.
template <typename T>
class auto_cloned_unique_ptr
{
private:
std::unique_ptr<T> up;
public:
// copy …
Run Code Online (Sandbox Code Playgroud) 通常,rvalues可以绑定到const引用(const SomeType&
).它内置于语言中.但是,std::reference_wrapper<const T>
不接受rvalue作为其构造函数参数,因为故意删除了相应的重载.这种不一致的原因是什么?std::reference_wrapper
当我们必须传递值但希望保留引用语义时,"广告"作为引用变量的替代.
换句话说,如果const &
绑定的右值被认为是安全的,因为它内置于语言中,为什么C++ 11的设计者不允许包含rvalues std::reference_wrapper<const T>
?
什么时候会派上用场,你可能会问.例如:
class MyType{};
class Foo {
public:
Foo(const MyType& param){}
};
class MultiFoo {
public:
MultiFoo(std::initializer_list<std::reference_wrapper<const MyType>> params){}
};
int main()
{
Foo foo{MyType{}}; //ok
MultiFoo multiFoo{MyType{}, MyType{}}; //error
}
Run Code Online (Sandbox Code Playgroud) 我经常在我的项目中使用"依赖注入"模式.在C++中,通过传递原始指针来实现它是最容易的,但现在使用C++ 11,高级代码中的所有内容都应该可以通过智能指针来实现.但这个案例的最佳做法是什么?性能并不重要,干净且易懂的代码对我来说更重要.
让我举一个简化的例子.我们有一个使用里面距离计算的算法.我们希望能够用不同的距离度量(Euclidean,Manhattan等)替换此计算.我们的目标是能够说出类似的话:
SomeAlgorithm algorithmWithEuclidean(new EuclideanDistanceCalculator());
SomeAlgorithm algorithmWithManhattan(new ManhattanDistanceCalculator());
Run Code Online (Sandbox Code Playgroud)
但有智能指针,以避免手动new
和delete
.这是一个使用原始指针的可能实现:
class DistanceCalculator {
public:
virtual double distance(Point p1, Point p2) = 0;
};
class EuclideanDistanceCalculator {
public:
virtual double distance(Point p1, Point p2) {
return sqrt(...);
}
};
class ManhattanDistanceCalculator {
public:
virtual double distance(Point p1, Point p2) {
return ...;
}
};
class SomeAlgorithm {
DistanceCalculator* distanceCalculator;
public:
SomeAlgorithm(DistanceCalculator* distanceCalculator_)
: distanceCalculator(distanceCalculator_) {}
double calculateComplicated() {
...
double dist = distanceCalculator->distance(p1, p2);
...
}
~SomeAlgorithm(){ …
Run Code Online (Sandbox Code Playgroud) 我们需要一直格式化字符串.能说:真是太好了
std::string formattedStr = format("%s_%06d.dat", "myfile", 18); // myfile_000018.dat
Run Code Online (Sandbox Code Playgroud)
有这样的C++方式吗?我考虑过一些替代方案
snprintf
:使用原始char
缓冲区.在现代C++代码中不太好用.std::stringstream
:不支持格式模式字符串,而是必须将笨拙的iomanip对象推送到流中.boost::format
:使用ad-hoc运算符重载%
来指定参数.丑陋.现在我们有C++ 11,对于可变参数模板有没有更好的方法?
在 Python 2 中有一个函数thread.interrupt_main()
,KeyboardInterrupt
当从子线程调用时,它会在主线程中引发异常。
这也可以_thread.interrupt_main()
在 Python 3 中使用,但它是一个低级的“支持模块”,主要用于其他标准模块。
在 Python 3 中这样做的现代方法是什么,大概是通过threading
模块,如果有的话?
python multithreading keyboardinterrupt python-multithreading python-3.x
以下代码工作,并按预期找到重载:
struct HasBuzz
{
void buzz() const {}
};
struct NoBuzz {};
template <typename T>
void foo(T const& t)
{
t.buzz();
}
void foo(NoBuzz const&){}
int main()
{
foo(HasBuzz{});
foo(NoBuzz{});
}
Run Code Online (Sandbox Code Playgroud)
但是,如果我用"通用引用"版本替换第一个重载,那么它就不再起作用了.找不到正确的过载NoBuzz
.
struct HasBuzz
{
void buzz() const {}
};
struct NoBuzz {};
template <typename T>
void foo(T&& t)
{
t.buzz();
}
void foo(NoBuzz const&){}
int main()
{
foo(HasBuzz{});
foo(NoBuzz{}); // error: NoBuzz has no member function buzz
}
Run Code Online (Sandbox Code Playgroud)
我能做些什么才能让它发挥作用?
c++11 ×5
c++ ×4
clone ×1
const ×1
python ×1
python-3.x ×1
rvalue ×1
templates ×1
unique-ptr ×1