如何保证按值返回的对象只有一个构造
How to guarantee only one construction of an object returned by value?
我正在尝试实现一个类,说Foo
,它遵循RAII,类的对象按值返回给客户端,即
class SomeClass {
public:
class Foo {
public:
~Foo() { /* follow raii */ }
private:
friend class SomeClass;
Foo() { /* follow raii */ }
};
Foo getFoo() { return Foo(); }
};
我的直接问题是,是否有任何方法可以确保在调用SomeClass::getFoo()
时只构造一个类型为Foo
的对象?我认为大多数编译器都知道只需要构造一个对象,但我知道在大多数情况下不能保证这一点。有更好的方法吗?
我试过返回一个boost::shared_ptr<Foo>
,只是在构造共享指针时分配一个Foo
对象,这工作得很好。然而,它似乎并不理想,因为它需要堆分配并且使接口不那么干净。
谢谢!
Visual Studio 2005编译器,所以我不认为R-val引用和c++ 11相关的特性是可用的。
你已经采取了最好的方法。编译器几乎肯定会忽略复制(或者实际上是c++ 11中的移动)。实际上,甚至调用代码中从返回值到某个对象的复制也可能被省略。所以这将只调用一个构造函数:
Foo foo = sc.getFoo();
允许省略这两个拷贝(或移动)的规则是:
如果要将未绑定到引用(12.2)的临时类对象复制/移动到具有相同cv- undefined类型的类对象,则可以通过将临时对象直接构造为省略的copy/move
的目标来省略复制/移动操作。
boost::optional + boost::in_place
如果复制构造函数是危险的,最好完全禁用它。虽然大多数编译器会在您的情况下省略副本,但有时可以禁用复制省略,例如-fno-elide-constructors -如果"相信"复制省略的代码碰巧运行在这样的设置上-可能会有烟火。
在c++ 98中,你可以使用boost::optional + boost::in_place——没有堆分配,因为boost::optional保留了足够的空间。并且保证不会有任何副本。
现场演示
#include <boost/utility/in_place_factory.hpp>
#include <boost/noncopyable.hpp>
#include <boost/optional.hpp>
#include <iostream>
#include <ostream>
using namespace boost;
using namespace std;
struct Foo: private noncopyable
{
explicit Foo(int i)
{
cout << "construction i=" << i << endl;
}
};
void make(optional<Foo> &foo)
{
foo = in_place(11);
}
int main()
{
optional<Foo> foo;
cout << "*" << endl;
make(foo);
cout << "!" << endl;
}
输出是:
*
construction i=11
!
此代码可以在MSVC2005上运行。
<标题>提振。移动h1> 一个选择是在c++ 98 - Boost.Move中使用move语义仿真。副本被禁用:
现场演示
#include <boost/move/utility.hpp>
#include <iostream>
#include <ostream>
using namespace std;
class Movable
{
BOOST_MOVABLE_BUT_NOT_COPYABLE(Movable)
bool own_resource;
public:
Movable()
: own_resource(true)
{}
~Movable()
{
cout << (own_resource ? "owner" : "empty") << endl;
}
Movable(BOOST_RV_REF(Movable) x)
: own_resource(x.own_resource)
{
x.own_resource = false;
}
Movable& operator=(BOOST_RV_REF(Movable) x)
{
own_resource = x.own_resource;
x.own_resource = false;
return *this;
}
};
Movable make()
{
return Movable();
}
int main()
{
Movable m = make();
}
输出是:
empty
empty
owner
此代码也可以在MSVC2005上工作。
<标题> c++ 11 h1> c++ 11中使用如下方法:
现场演示
struct Foo
{
Foo(const Foo &)=delete;
Foo(Foo &&)=delete;
Foo &operator=(const Foo&)=delete;
Foo &operator=(Foo &&)=delete;
Foo(int){}
};
Foo create()
{
//return Foo{0}; // ERROR: needs Foo(self &&)
return {0};
}
int main()
{
auto &&t=create();
}
Foo只被创建一次,它的复制和移动构造函数被删除- 保证不会有任何复制或移动。
标题>标题>- 在他自己的方法中,有可能将一个对象取消引用到另一个对象吗
- 我有一个对象,它将在整个程序的持续时间内实例化,但一个类成员不会,我应该动态分配它吗?
- 在 C++ 中声明 const 对象需要用户定义的默认构造函数.如果我有一个可变成员变量,为什么不呢?
- 我们可以有一个 setter 成员函数作为从 const 对象引用的 const 吗?
- C++是否有一个容器,每个类型最多存储一个对象
- Qt:在一个类中有一个QPainter对象的实例
- 如何让线程等待对象完全破坏?(对象也有一个线程)?
- 一个对象什么时候可以有非零大小的一个,但不能同时具有一个或多个字节的存储
- 当我们有纯虚函数时,如何煽动一个对象?
- 有没有办法将一个对象注入到另一个对象的结构中?
- 我有一个 Qt 对象的 2d 数组,我已经用值播种了这些对象。如何访问数组中特定对象的值并更改它们?
- 我在代码中有一个错误,错误是:(智能感知:不允许抽象类类型"HourlyWorker"的对象:)
- 类有一个自类型的对象
- 是否有一个函数可以显示我创建的类中的对象到 QTextBrowser 中?
- 在堆栈上有一个对象,而不是在函数的整个生命周期内
- 得到错误"left of '.toString' must have class/struct/union",即使 toString 应该有一个合适的对象
- 在c++中有条件地创建一个对象
- 你如何断言一个对象在c++中有一个特定的方法
- C++如果我有一个对象指针,是在堆栈或堆上分配的方法变量
- 我有一个对象数组,我想发出一个包含这些对象中的一个的信号。但信号不能是指针