不可复制对象和值初始化:g ++ vs msvc [英] non-copyable objects and value initialization: g++ vs msvc

查看:192
本文介绍了不可复制对象和值初始化:g ++ vs msvc的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我看到g ++和msvc之间的一些不同的行为围绕值初始化不可复制对象。考虑一个不可复制的类:

I'm seeing some different behavior between g++ and msvc around value initializing non-copyable objects. Consider a class that is non-copyable:

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_;
};

和使用值初始化的模板,以便该值将获得已知的值, POD:

and a template that uses value initialization so that the value will get a known value even when the type is POD:

template <class T>
void doit()
{
    T t = T();
    ...
}

p>

and trying to use those together:

doit<noncopyable>();

这在从VC ++ 9.0的msvc工作正常,但在每个版本的g ++失败我测试这包括版本4.5.0),因为复制构造函数是私有的。

This works fine on msvc as of VC++ 9.0 but fails on every version of g++ I tested this with (including version 4.5.0) because the copy constructor is private.

两个问题:


  1. 哪些行为符合标准?

  2. 任何有关如何在gcc中解决这个问题的建议(并且清楚,将其更改为 T t; code>不是可接受的解决方案,因为这会打破POD类型)。

PS我看到了与boost :: noncopyable相同的问题。

P.S. I see the same problem with boost::noncopyable.

推荐答案

在MSVC中看到的行为是一个扩展,在下一页(强调我的)中以迂回的方式记录下来 http:// msdn.microsoft.com/en-us/library/0yw5843c.aspx

The behavior you're seeing in MSVC is an extension, though it's documented as such in a roundabout way on the following page (emphasis mine) http://msdn.microsoft.com/en-us/library/0yw5843c.aspx:


等号初始化语法不同从函数式语法,即使生成的代码在大多数情况下是相同的。区别在于,当使用等号语法时,编译器必须表现为发生以下事件序列:

The equal-sign initialization syntax is different from the function-style syntax, even though the generated code is identical in most cases. The difference is that when the equal-sign syntax is used, the compiler has to behave as if the following sequence of events were taking place:



  • 将临时对象复制到该对象。

在编译器可以执行这些步骤之前,构造函数必须可访问。即使编译器可以消除大多数情况下的临时创建和复制步骤,一个不可访问的副本构造函数会导致等号初始化失败(下的)。

The constructor must be accessible before the compiler can perform these steps. Even though the compiler can eliminate the temporary creation and copy steps in most cases, an inaccessible copy constructor causes equal-sign initialization to fail (under /Za, /Ze (Disable Language Extensions)).

请参阅Ben Voigt的回答解决方法,它是 boost :: value_initialized ,正如litb在Ben的回答的评论中指出的。 boost :: value_initalized 的文档对此问题,解决方法以及各种编译器问题的一些缺陷进行了大量讨论。

See Ben Voigt's answer for a workaround which is a simplified version of boost::value_initialized, as pointed out by litb in a comment to Ben's answer. The docs for boost::value_initalized has a great discussion of the problem, the workaround, and some of the pitfalls of various compiler issues.

这篇关于不可复制对象和值初始化:g ++ vs msvc的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆