我今天遇到了一个非常微妙的问题,我想征求您的意见。

考虑以下花园式的共享体习语类:

struct S
{
    S() : p_impl(new impl) {}
private:
    struct impl;
    boost::shared_ptr<impl> p_impl;
};

当您尝试按以下方式将它们放入 vector 时,乐趣就会出现:
std::vector<S> v(42);

现在,至少在 MSVC 8 中,v 中的所有元素共享相同的 impl 成员。实际上,导致这种情况的原因是 vector 构造函数:
template <typename T, typename A = ...>
class vector
{
    vector(size_t n, const T& x = T(), const A& a = A());
    ...
};

在场景下,只有一个 S 对象被默认构造,从它复制 nvector 元素。

现在,在 C++11 中,有右值引用。所以它不能像这样工作。如果 vector 构造为
std::vector<S> v(42);

那么很可能,实现将选择默认构造 vector 内的 n 对象,因为复制构造可能不可用。在这种情况下,这将是一个突破性的变化。

我的问题是:
  • C++03 标准是否要求 std::vector 必须具有如上定义的构造函数,即。使用默认参数?特别是是否保证 vector 对象的条目被复制而不是默认构造?
  • C++11 标准对同一点有何看法?
  • 我认为这是在 C++03 和 C+11 之间进行重大更改的可能性。这个问题有调查过吗?解决了 ?

  • PS:请不要评论上面S类的默认构造函数。就是这样或者实现了某种形式的惰性构造。

    最佳答案



    是的,指定的行为是 x 被复制 n 次,以便容器被初始化为包含 n 元素,这些元素都是 x 的拷贝。



    在 C++11 中,这个构造函数已经变成了两个构造函数。

    vector(size_type n, const T& x, const Allocator& = Allocator()); // (1)
    explicit vector(size_type n);                                    // (2)
    

    除了它不再有第二个参数的默认参数这一事实外, (1) 的工作方式与在 C++03 中的工作方式相同:x 被复制 0x2313413 次。

    代替 n 的默认参数,添加了 (2) 。此构造函数值初始化容器中的 x 个元素。不制作任何拷贝。

    如果您需要旧行为,则可以通过向构造函数调用提供第二个参数来确保调用 (1) :
    std::vector<S> v(42, S());
    



    是的,正如您的示例所示,这确实是一个突破性的变化。

    由于我不是 C++ 标准化委员会的成员(并且我没有特别密切关注邮件中与库相关的论文),我不知道讨论了这种重大更改的程度。

    关于c++ - std::vector、默认构造、C++11 和重大更改,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/5759232/

    10-17 01:27