(这个问题的灵感来自Nicolai Josuttis的CppCon 2017演讲.)
考虑以下源文件(对于对象,而不是完整的程序):
#include <string>
class C {
std::string s_;
public:
C(std::string s) : s_(s) { };
void bar();
};
void foo() {
std::string hello { "The quick brown fox jumped over the lazy dog" };
C c { hello };
c.bar();
}
Run Code Online (Sandbox Code Playgroud)
即使使用-O2(甚至使用-O3),似乎字符串构造函数被调用三次.具体而言,s构造,仅用于构造s_,然后被破坏.我的问题:
s_从ctor的参数构造,而不是构造s?s_从s,看到后者是如何闲置?s构造正确,编译器不能避免构造hello,看看它没有其他用途吗?或者至少离开它?我刚刚阅读了关于rvalue引用的内容,下面是我所指的代码
vector<string> v;
string s = "hello";
v.push_back(s);
cout << s << endl;
cout << v[0] << endl;
return 0
Run Code Online (Sandbox Code Playgroud)
我的问题是,到目前为止,每当我看到对象(或字符串)的向量时,我主要看到插入操作如上所述.相反,如果我这样做,v.push_back(std::move(s))那么我不会不必要地创建重复的对象.
这应该是向STL添加对象的正确方法,我们关心的只是容器中的数据而不是其他变量.
我正在编写一个类,该类需要用于过滤成员容器的高效函数(可以说std::vector)。此功能应具有类似于以下内容的界面:
void filter(std::vector<SomeType>& items, const std::vector<int>& inds);
Run Code Online (Sandbox Code Playgroud)
该函数应使容器items处于以下状态:-索引所指向的项目inds应被删除-其他项目应保留在容器中并保持初始顺序。
为简单起见,假设这inds是一个完美的容器,每个操作均带有O(1),并且所有索引均有效且无重复。
我的想法是创建第二个容器,保留所需的空间,然后将std::move所有未索引的元素(通过)移动inds到该新容器中;然后只需交换旧容器和新容器即可。
例如这样:
void filter(std::vector<SomeType>& items, const std::vector<int>& inds)
{
std::vector<SomeType> new_items{};
new_items.reserve( items.size() - inds.size() );
for(size_t i = 0; i < items.size(); ++i)
if( contains( inds, i ) ) // magic O(1) function, never mind
new_items.push_back( std::move( items[i] ) );
items.swap(new_items);
}
Run Code Online (Sandbox Code Playgroud)
我的问题是:
1)在(或其他标准容器)std::move内部的某个元素上使用后,vector是否会出现诸如双重破坏这些元素的问题?
2)是否有标准方法可以有效地进行此类过滤?
我跑了一些代码
template<class InputIt, class T>
constexpr // since C++20
T accumulate(InputIt first, InputIt last, T init)
{
for (; first != last; ++first) {
init = std::move(init) + *first; // std::move since C++20
}
return init;
}
Run Code Online (Sandbox Code Playgroud)
我有个问题。为什么我们必须使用 std::move oninit即使init是int?
在cpp 参考中的以下示例中:
#include <iostream>
#include <utility>
#include <vector>
#include <string>
int main()
{
std::string str = "Hello";
std::vector<std::string> v;
// uses the push_back(const T&) overload, which means
// we'll incur the cost of copying str
v.push_back(str);
std::cout << "After copy, str is \"" << str << "\"\n";
// uses the rvalue reference push_back(T&&) overload,
// which means no strings will be copied; instead, the
// Contents of str will be moved into the vector. This is
// less …Run Code Online (Sandbox Code Playgroud) 我有以下代码,当它的析构函数被调用时它没有打印正确的字符串
struct Tracer {
Tracer( const std::string& name_in)
: name{ name_in } {
std::cout << name << " constructed.\n";
}
~Tracer() {
std::cout << name << " destructed.\n";
}
private:
const std::string& name;
};
Tracer static_tracer{ "static Tracer" };
int main() {
}
Run Code Online (Sandbox Code Playgroud)
输出:构造的静态 Tracer。
?1?问?
但以下代码按预期工作:
Tracer( std::string name_in)
: name{ std:move(name_in) } {
std::cout << name << " constructed.\n";
}
private:
std::string name;
Run Code Online (Sandbox Code Playgroud)
输出:构造的静态 Tracer。
静态示踪剂被破坏。
或者当使用 stringview 或简单的 sting 时。
我们是如何在第一个代码中的程序终止期间丢失对字符串的引用的?
我们也不应该使用 move() 来释放对字符串的引用,因为它有一个构造函数作用域吗?
谢谢!
我试图理解移动构造函数。
我在类的构造函数中分配内存并在析构函数中销毁它。
当我尝试移动类时,我仍然有一个双空闲。
#include <algorithm>
class TestClass
{
public:
TestClass() {a_ = new int[1];}
TestClass(TestClass const& other) = delete;
TestClass(TestClass && other) noexcept // = default;
{
this->a_ = std::move(other.a_);
}
~TestClass() {delete[] a_;}
private:
int* a_ = nullptr;
};
int main( int argc, char** argv )
{
TestClass t;
TestClass t2 = std::move(t);
}
Run Code Online (Sandbox Code Playgroud)
为什么std::move不改为 nullptr other.a_?
如果移动构造函数是默认的,我也有同样的问题。
我发现了以下问题,但我仍然不知道为什么移动运算符不将源变量更改为默认值。
以下是我正在尝试的玩具代码...我理解第一个和第二个。第一个将所有权授予_p. 第二个复制p到_p. 但第三个我没看懂……
std::move的是什么const shared_ptr &意思?谢谢。
class P { };
class A {
public:
// first one
A(std::shared_ptr<P> &p, int) : _p(std::move(p))
{
std::cout << "1st Ctor: "
<< p.use_count() << ", " << _p.use_count() << std::endl;
}
// second one
A(const std::shared_ptr<P> &p, std::string) : _p(p)
{
std::cout << "2nd Ctor: "
<< p.use_count() << ", " << _p.use_count() << std::endl;
}
// third one
A(const std::shared_ptr<P> &p) : _p(std::move(p)) …Run Code Online (Sandbox Code Playgroud) 我有 3 个问题:
std::move移动内置类型吗?int a = 10;
int b = std::move(a);
Run Code Online (Sandbox Code Playgroud)
会a是无效值吗?
std::move移动指针int *a = new int[10];
int *b = std::move(a);
Run Code Online (Sandbox Code Playgroud)
会a变成无效指针还是nullptr?
std::move移动ac阵列吗?struct S {
int array[10];
}
S a;
for(int i=0; i<10; i++)
a.array[i]=1;
S b;
b = std::move(a);
Run Code Online (Sandbox Code Playgroud)
会a.array变成无效数组吗?
当我在std::move没有任何分配的情况下使用时会发生什么?
std::string s = "Moving";
std::move(s); //What happens on this line to s?
//is s still valid here?
Run Code Online (Sandbox Code Playgroud) c++ ×10
stdmove ×10
c++11 ×5
c++17 ×1
containers ×1
copy-elision ×1
move ×1
reference ×1
shared-ptr ×1
stdstring ×1
stl ×1
string ×1