首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >std::vector、默认构造、C++11和中断更改

std::vector、默认构造、C++11和中断更改
EN

Stack Overflow用户
提问于 2011-04-23 03:28:30
回答 2查看 3.2K关注 0票数 54

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

考虑下面这个普通的共享主体成语类:

代码语言:javascript
复制
struct S
{
    S() : p_impl(new impl) {}
private:
    struct impl;
    boost::shared_ptr<impl> p_impl;
};

有趣的是,当您尝试将这些向量放入向量时,请使用以下方法:

代码语言:javascript
复制
std::vector<S> v(42);

现在,至少在MSVC8中,v中的所有元素都共享相同的impl成员。实际上,导致这种情况的是vector构造函数:

代码语言:javascript
复制
template <typename T, typename A = ...>
class vector
{
    vector(size_t n, const T& x = T(), const A& a = A());
    ...
};

在这些场景下,只有一个S对象得到默认构造,vectorn元素是从该对象复制而来的。

现在,在C++11中,有了右值引用。所以它不能像这样工作。如果vector被构造为

代码语言:javascript
复制
std::vector<S> v(42);

然后,最有可能的是,实现将选择缺省构造向量内的n对象,因为复制构造可能不可用。在这种情况下,这将是一个突破性的变化。

我的问题是:

  1. 做了C++03标准要求std::vector必须有一个如上定义的构造函数,即。使用默认参数?特别是,是否可以保证复制矢量对象的条目而不是默认构造?
  2. C++11标准对这一点做了什么规定?
  3. 我认为这是C++03和C+11之间发生重大变化的可能性。这个问题已经调查过了吗?解决了?

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

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2011-04-23 03:35:01

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

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

C++11标准对这一点有什么规定?

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

代码语言:javascript
复制
vector(size_type n, const T& x, const Allocator& = Allocator()); // (1)
explicit vector(size_type n);                                    // (2)

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

为了代替x的默认参数,添加了(2)。此构造函数用于初始化容器中的n元素。不会创建任何副本。

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

代码语言:javascript
复制
std::vector<S> v(42, S());

我认为这是C++03和C++11之间发生重大变化的可能性。我认为这是C++03和C++11之间发生重大变化的可能性。这个问题已经调查过了吗?解决了吗?

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

由于我不是C++标准化委员会的成员(我也没有在邮件中特别关注与图书馆相关的论文),我不知道在多大程度上讨论了这一突破性的变化。

票数 46
EN

Stack Overflow用户

发布于 2012-03-02 06:42:39

我认为你描述的用例的解决方案不是最优的,也不是完整的,这就是为什么你在升级到C++11时遇到了问题。

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

假设你需要N个对象的M个向量,如果你选择第一个场景,会分配多少次共享内存?它是M,但是如果我们想创建包含MxN对象的向量,为什么我们需要分配M次内存呢?

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

在你的例子中,你违反了正确的语义滥用复制构造函数,那就是: 1)不明显,2)不是最优的,现在你必须付出代价。

票数 -3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/5759232

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档