C ++-std :: vector,默认构造,C ++ 11和重大更改

我今天遇到一个非常微妙的问题,我想请您发表意见。

考虑以下花园品种共享体习语类:

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

当您尝试通过以下方式将它们放入向量中时,会很有趣:

std::vector<S> v(42);

现在,至少使用MSVC 8,S中的所有元素都共享相同的n成员。 实际上,导致此问题的原因是vector构造函数:

template <typename T, typename A = ...>
class vector
{
    vector(size_t n, const T& x = T(), const A& a = A());
    ...
};

在场景下,仅默认构造了一个S对象,并从其中复制了vectorn元素。

现在,在C ++ 11中,有右值引用。 因此它不能像这样工作。 如果将S构造为

std::vector<S> v(42);

那么最有可能的是,实现可能会选择默认在向量内部构造S对象,因为复制构造可能不可用。 在这种情况下,这将是一个重大变化。

我的问题是:

  1. C ++ 03标准是否要求S必须具有上面定义的构造函数,即。 带有默认参数? 特别是,可以保证矢量对象的条目被复制而不是默认构造的吗?
  2. 关于这一点,C ++ 11标准怎么说?
  3. 我认为这是在C ++ 03和C + 11之间进行重大更改的可能性。 这个问题已经调查过了吗? 解决了 ?

PS:请不要对上面的类S的默认构造函数发表评论。 正是这种或实施某种形式的惰性构造。

2个解决方案
46 votes

C ++ 03标准是否要求std::vector必须具有如上所述定义的构造函数,即具有默认参数? 特别是可以保证矢量对象的条目被复制而不是默认构造吗?

是的,指定的行为是将x复制了n次,以便容器初始化为包含n元素,这些元素都是x的副本。


关于这一点,C ++ 11标准怎么说?

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

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

(2)除了不再为第二个参数提供默认参数外,(1)的工作方式与C ++ 03中的工作方式相同:将x复制n次。

代替x的默认参数,添加了(2)。 此构造函数值初始化容器中的n元素。 没有副本。

如果您需要旧的行为,则可以通过为构造函数调用提供第二个参数来确保调用(1):

std::vector<S> v(42, S());

我认为这是在C ++ 03和C ++ 11之间进行重大更改的可能性。 我认为这是在C ++ 03和C ++ 11之间进行重大更改的可能性。 这个问题被调查了吗? 解决了?

是的,正如您的示例所示,这确实是一个重大变化。

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

James McNellis answered 2020-01-14T15:15:10Z
-3 votes

我认为您描述的用例解决方案不是最佳且不完整的,这就是为什么升级到C ++ 11时遇到问题的原因。

C ++始终关心语义,当您使用c ++编写程序时,最好理解一下语义。 因此,在您的情况下,您希望创建N个对象,但是在不更改它们的同时,希望它们共享相同的内存以进行优化。 不错的主意,但是如何做到这一点:1)复制构造函数。2)静态实现+复制构造函数。您是否考虑过两种解决方案?

考虑您需要N个对象的M个向量,如果选择第一种情况,将分配多少次共享内存? 它是M,但是如果要创建包含MxN个对象的向量,为什么为什么需要分配M次内存?

因此,此处的正确实现是默认情况下指向静态内存,并且仅当对象更改时才分配内存。 在这种情况下,分配N个对象的M个向量将为您提供... 1个“共享”内存分配。

在您的情况下,您违反了正确的语义滥用副本构造函数,即:1)不明显2)不是最佳现在您必须还清。

Alexey Sergeev answered 2020-01-14T15:15:49Z
translate from https://stackoverflow.com:/questions/5759232/stdvector-default-construction-c11-and-breaking-changes