标签: std

可以使用placement-new和vector :: data()来替换向量中的元素吗?

有两个关于替换不可赋值的向量元素的问题:

对象不可分配的典型原因是其类定义包含const成员,因此将其operator=删除.

std::vector要求其元素类型可分配.事实上,至少使用GCC,当对象不可分配时,直接赋值(vec[i] = x;),erase()以及insert()替换元素的组合都不起作用.

可以使用像下面这样的函数来使用vector::data(),直接元素销毁和使用复制构造函数的新元素来替换元素而不会导致未定义的行为吗?

template <typename T>
inline void replace(std::vector<T> &vec, const size_t pos, const T& src)
{
  T *p = vec.data() + pos;
  p->~T();
  new (p) T(src);
}
Run Code Online (Sandbox Code Playgroud)

下面是一个使用函数的例子.这在GCC 4.7中编译并且似乎有效.

struct A
{
  const int _i;
  A(const int &i):_i(i) {}
};

int main() {
  std::vector<A> vec;
  A c1(1);
  A c2(2);

  vec.push_back(c1);
  std::cout << vec[0]._i << std::endl;

  /* To replace the element …
Run Code Online (Sandbox Code Playgroud)

c++ vector std placement-new c++11

17
推荐指数
1
解决办法
1531
查看次数

为什么C++ 14中没有std :: allocate_unique函数?

为什么在shared_ptr没有allocate_unique的unique_ptr情况下有allocate_shared?
我想使用自己的分配器创建一个unique_ptr:我是否必须自己分配缓冲区然后将其分配给unique_ptr?
这似乎是一个明显的成语.

c++ std c++14

17
推荐指数
2
解决办法
3032
查看次数

高效的C++方式,为C++字符串中的特殊符号(")赋予字面意义

我想说这个:

<script src = "Script2.js" type = "text/javascript"> < / script>
Run Code Online (Sandbox Code Playgroud)

在一个std::string所以我\在每个双引号(")之前附加一个()符号,给它一个字面含义",而不是像这样的C++中的字符串分界:

std::string jsFilesImport = "<script src = \"Script2.js\" type = \"text/javascript\"> < / script>\""
Run Code Online (Sandbox Code Playgroud)

如果我有string很多("),则\每个(")的添加()变得困难.有一种简单的方法可以在C++中实现这一点吗?

c++ string std string-literals c++11

17
推荐指数
1
解决办法
1243
查看次数

为什么std中仍然没有启用范围的归约算法?

唯一可用的选项是std::ranges::for_each简单的基于范围的for循环。没有对应的std::accumulate,std::reducestd::inner_productstd::ranges::reduce如果有的话就足够了;内积可以结合reduce和zip来实现。回到基于迭代器的算法是令人失望的。为个人代码库调整reduce并不是什么大问题,但恕我直言,std函数更可取。我想知道 std lib 或 23 地平线上是否有这样的功能。

问候,FM。

c++ std range c++23 isocpp

17
推荐指数
1
解决办法
2335
查看次数

为什么 std::barrier 分配?

为什么std::barrier在堆上分配内存而不在堆上分配内存std::latch

它们之间的主要区别是std::barrier可以重用而std::latch不能,但我找不到解释为什么这会让前者分配内存。

c++ multithreading std c++20

17
推荐指数
1
解决办法
1201
查看次数

std::common_reference_with 在元组上的行为不一致。哪个是对的?

背景:

我正在尝试移植一个库以在 MSVC 上进行编译。该库将数据存储在向量元组 ( std::tuple<std::vector<Ts>...>) 中,并使用自定义迭代器同时迭代所有向量(类似于 zip_iterator 的作用)。

迭代器定义的类型如下所示(假设Ts...-> <int, int>):

`value_type` is `std::tuple<int, int>`  
`reference`  is `std::tuple<int&, int&>`
Run Code Online (Sandbox Code Playgroud)

问题是,在最新的 MSVC (v. 19.35) 上,这个迭代器不满足 的概念std::input_iterator,而在 gcc/clang 上却满足它。

经过进一步调查,我发现失败是由于std::common_reference元组上的概念行为不一致造成的。

问题:

以下static_assert内容在 MSVC 上失败,而在 gcc/clang 上不会失败

using T = std::tuple<int, int>&;
using U = std::tuple<int&, int&>;
static_assert(std::common_reference_with<T, U>, "failed common_reference_with");
Run Code Online (Sandbox Code Playgroud)

这是Godbolt上的(还有一个迭代器示例)

问题:

像这样的类型std::tuple<int, int>&应该有一个“ common_reference_withstd::tuple<int&, int&>吗?MSVC 说不,gcc 说可以。
根据 C++20 及以后的标准,这两种行为中的哪一种是预期的?

有没有什么简单的方法可以使这个迭代器成功通过 MSVC 上的迭代器概念检查(即强制这两种类型具有共同的引用)? …

c++ tuples std language-lawyer c++-concepts

17
推荐指数
1
解决办法
560
查看次数

为什么在这种情况下需要指定默认构造对象的类型?

我不明白为什么在foobar下面我需要指定std::vector<int>{}而在foobar2我不需要:

#include <iostream>
#include <memory>
#include <vector>
#include <tuple>

std::tuple<std::unique_ptr<int>, std::vector<int>> foobar() {
    std::unique_ptr<int> test = std::make_unique<int>(42);
    return { std::move(test), {} };    // <= this is a syntax error
    // return { std::move(test), std::vector<int>{} }  // <= this compiles...
}

std::tuple<int, std::vector<int>> foobar2() {
    return { {},  {} };
}

int main() {
    std::cout << *std::get<0>(foobar()) << "\n";
    std::cout << std::get<0>(foobar2()) << "\n";
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

来自 GCC 的错误消息是

<source>: In function 'std::tuple<std::unique_ptr<int, std::default_delete<int> …
Run Code Online (Sandbox Code Playgroud)

c++ std default-constructor stdtuple

17
推荐指数
1
解决办法
678
查看次数

在保留原始顺序的同时擦除/删除多个std :: vector元素的最有效方法?


我有一个std::vector<int>和第二个容器持有迭代器或索引(没有键,我希望不断访问元素)到这个向量用于删除目的.让我们假设我有一个1000个元素的向量,并想要删除其中的200个元素.在删除操作之后,未删除元素的顺序应该与之前相同.

我在问题的第一个版本中错过了另一件事:价值观是独一无二的.他们是身份.

你如何在安全(关于stl规则)和有效方式(传统的决定是最终的)中做到这一点?

我想到的可能性方法:

  • 所述擦除remove惯用法(http://en.wikipedia.org/wiki/Erase-remove_idiom):最初为其中满足条件(包括直链的搜索)的元素的删除,但我认为有尺寸1这种方法可能是范围习惯于已经给定的迭代器和虚拟条件.问题:保留的元素的原始顺序是否比最后一种方法更高效?
  • 循环遍历索引并使用vector.erase(vector.begin()+index+offset)同时删除元素,同时保持在容器中删除索引以计算偏移量.可以使用std::lower_bound已经移除的元素的容器来确定每次移除迭代的该偏移.问题:由于随机位置删除,很多binary_searches用于获取偏移量和大量移动操作.
  • 目前我正在做以下事情:获取要删除的元素的所有迭代器.根据向量中的位置按降序对它们进行排序,并在它们上面循环以进行最终删除vector.erase.现在我没有使任何迭代器失效,除了删除本身之外没有向量重新排列操作.问题:很多排序

那么,你会如何解决这个问题呢?有什么新想法吗?有什么建议?

感谢您的输入.

萨沙

编辑/更新/拥有结果:我实现了擦除 - 删除习惯用法,这也是KennyTM提到的,带有一个基于boost :: dynamic_bitset中的查找谓词,并且它的速度非常快.此外,我尝试了PigBen的move-and-truncate方法(也由Steve Jessop提到),它也在它的while循环中访问bitset.对我的数据来说,两者似乎同样快.我试图删除100个1000个元素(无符号整数)中的100个,这100个删除了1M次并且没有显着差异.因为我认为基于stl的擦除删除成语更"天生",我选择了这种方法(KennyTM也提到了参数).

c++ algorithm performance stl std

16
推荐指数
2
解决办法
2万
查看次数

std :: vector差异

如何确定2个向量的差异是什么?

我有vector<int> v1vector<int> v2;

我正在寻找的是vector<int> vDifferences仅包含仅在v1或中的元素v2.

有没有标准的方法来做到这一点?

c++ std

16
推荐指数
1
解决办法
1万
查看次数

C++:"vector <int> :: size_type variable" - 以这种方式声明的重点是什么?

我认为这是一个非常基本的问题,但我无法弄明白.

我习惯于在C++中使用数组,但我现在开始学习矢量.我正在制作一个测试代码,我遇到了一个问题.

首先,这是我制作的代码:

#include <iostream>
#include <vector>
#include <numeric>
using namespace std;

int main(){
  vector<double> score(10);

  for(vector<double>::size_type i=0;i<20;i++) {
    cout<<"Enter marks for student #"<<i+1<<":"<<flush;
    cin>>score[i];
  }

  double total = accumulate(score.begin(), score.end(),0);

  cout<<"Total score:"<<total<<endl<<"Average score:"<<total/score.size()<<flush;

  return 0;
}
Run Code Online (Sandbox Code Playgroud)

for第9行的句子中,我宣称i是一种vector<double>::size_type类型(因为我被告知要这样做).我测试了上面用上面所说的类型取代的代码int,它工作得非常好.为什么比较vector<double>::size_type优先int

c++ types vector std

16
推荐指数
2
解决办法
2452
查看次数