R S*_*hko 4 c++ gcc visual-c++ value-initialization
我看到g ++和msvc在初始化不可复制对象的值之间有一些不同的行为.考虑一个不可复制的类:
class noncopyable_base
{
public:
noncopyable_base() {}
private:
noncopyable_base(const noncopyable_base &);
noncopyable_base &operator=(const noncopyable_base &);
};
class noncopyable : private noncopyable_base
{
public:
noncopyable() : x_(0) {}
noncopyable(int x) : x_(x) {}
private:
int x_;
};
Run Code Online (Sandbox Code Playgroud)
和一个使用值初始化的模板,以便即使类型为POD,该值也将获得已知值:
template <class T>
void doit()
{
T t = T();
...
}
Run Code Online (Sandbox Code Playgroud)
并尝试将它们一起使用:
doit<noncopyable>();
Run Code Online (Sandbox Code Playgroud)
从VC++ 9.0开始,这在msvc上运行正常,但在每个版本的g ++上都失败了我用它(包括版本4.5.0)进行了测试,因为复制构造函数是私有的.
两个问题:
T t;为不可接受的解决方案,因为这会打破POD类型).PS我看到与boost :: noncopyable相同的问题.
你在MSVC中看到的行为是一个扩展,虽然它在下一页以迂回的方式记录(强调我的)http://msdn.microsoft.com/en-us/library/0yw5843c.aspx:
等号初始化语法与函数式语法不同,即使生成的代码在大多数情况下是相同的.不同之处在于,当使用等号语法时,编译器必须表现得好像发生了以下事件序列:
- 创建与正在初始化的对象类型相同的临时对象.
- 将临时对象复制到对象.
在编译器执行这些步骤之前,必须可以访问构造函数.即使编译器在大多数情况下可以消除临时创建和复制步骤,但是无法访问的复制构造函数会导致等号初始化失败(在/ Za,/ Ze(禁用语言扩展)下).
请参阅Ben Voigt的解决方案,该解决方案是一个简化版本boost::value_initialized,正如Litb在对Ben的回答的评论中指出的那样.这些文档对boost::value_initalized问题,解决方法以及各种编译器问题的一些缺陷进行了很好的讨论.
我不认为需要模板元编程.尝试
template <class T>
void doit()
{
struct initer { T t; initer() : t() {} } inited;
T& t = inited.t;
...
}
Run Code Online (Sandbox Code Playgroud)