该程序试图将一个字符串移出一个函数并用它来构造另一个字符串:
#include <iostream>
#include <string>
#include <utility>
std::string && Get_String(void);
int main(){
std::string str{Get_String()};
std::cout << str << std::endl;
return 0;
}
std::string && Get_String(void){
std::string str{"hello world"};
return std::move(str);
}
Run Code Online (Sandbox Code Playgroud)
程序编译,但执行时会出现段错误.
这是我的理由: Get_String将创建一个本地字符串.在字符串超出范围之前,需要创建并返回该字符串的副本.该副本将用于在main中构造字符串.但是,如果我将字符串移出函数,则不需要复制.
为了理解移动语义,有人可以解释为什么我在做什么,可能没有任何意义.是否可以将对象移出函数?
编辑:
如果我更改函数签名,它编译并正确运行:
std::string && Get_String(void);
Run Code Online (Sandbox Code Playgroud)
至
std::string Get_String(void);
Run Code Online (Sandbox Code Playgroud)
在这种情况下,在返回期间移动字符串是否仍然更有效?
说我有以下功能
void doWork(Widget && param) // param is an LVALUE of RRef type
{
Widget store = std::move(param);
}
Run Code Online (Sandbox Code Playgroud)
为什么我需要param回到rvalue std::move()?是不是很明显,paramrvalue 的类型是因为它在函数签名中被声明为右值引用?不应该仅仅根据这个原则自动调用移动构造函数吗?
为什么不默认发生这种情况?
c++ rvalue-reference move-constructor lvalue-to-rvalue stdmove
我正在查看关于multimap的MSDN文档,并发现它有一个成员函数multimap :: emplace().以下是该成员函数的示例.
int main( ) {
using namespace std;
multimap<int, string> m1;
pair<int, string> is1(1, "a");
m1.emplace(move(is1));
}
Run Code Online (Sandbox Code Playgroud)
看来,emplace()和move()是C++ 0x中.有人可以帮我解释一下吗?我读到了move(),但我真的不明白它做了什么(引擎盖下).
假设我有以下代码:
class B { /* */ };
class A {
vector<B*> vb;
public:
void add(B* b) { vb.push_back(b); }
};
int main() {
A a;
B* b(new B());
a.add(b);
}
Run Code Online (Sandbox Code Playgroud)
假设在这种情况下,B*可以处理所有原始指针unique_ptr<B>.
令人惊讶的是,我无法找到如何使用转换此代码unique_ptr.经过几次尝试,我想出了以下代码,它编译:
class A {
vector<unique_ptr<B>> vb;
public:
void add(unique_ptr<B> b) { vb.push_back(move(b)); }
};
int main() {
A a;
unique_ptr<B> b(new B());
a.add(move(b));
}
Run Code Online (Sandbox Code Playgroud)
所以我的简单问题是:这是实现它的方式,特别是,这是move(b)唯一的方法吗?(我在想rvalue引用,但我不完全理解它们.)
如果你有一个完整的移动语义解释链接unique_ptr,我无法找到,请不要犹豫,分享它.
编辑根据http://thbecker.net/articles/rvalue_references/section_01.html,我的代码似乎没问题.
实际上,std :: move只是语法糖.对于类X的对象x,move(x)与以下内容相同:
static_cast <X&&>(x)
Run Code Online (Sandbox Code Playgroud)
需要这两个移动函数,因为转换为右值引用:
我想知道在这个代码中for (auto& i : v),for (auto&& i : v)在基于范围的for循环之间有什么区别:
#include <iostream>
#include <vector>
int main()
{
std::vector<int> v = {0, 1, 2, 3, 4, 5};
std::cout << "Initial values: ";
for (auto i : v) // Prints the initial values
std::cout << i << ' ';
std::cout << '\n';
for (auto i : v) // Doesn't modify v because i is a copy of each value
std::cout << ++i << ' ';
std::cout << '\n';
for …Run Code Online (Sandbox Code Playgroud) 考虑到(x | r | l | pr | gl)值,我想到了以下问题:
考虑以下两个变量声明:
X x = ...;
Run Code Online (Sandbox Code Playgroud)
和
X&& x = ...;
Run Code Online (Sandbox Code Playgroud)
并承担了...做不提供的x值.
任何人都可以想到代码没有使用decltype,这会产生什么影响?在这两种情况下,(x)都会通过左值型X,不是吗?
移动语义的想法是,您可以从另一个临时对象(由右值引用引用)中获取所有内容,并将"所有内容"存储在对象中.这有助于避免在单个构造事物足够的情况下进行深度复制 - 因此您可以在rvalue对象中构造事物,然后将其移动到长寿命对象中.
为什么C++不允许将左值对象绑定到右值引用?两者都允许我更改引用的对象,因此在访问引用对象的内部方面对我没有任何区别.
我能猜到的唯一原因是函数重载模糊问题.
从“死”的unique_ptr中使用operator *的返回值是不好的。
以下代码可以编译,但是结果当然是未定义行为:
auto& ref = *std::make_unique<int>(7);
std::cout << ref << std::endl;
Run Code Online (Sandbox Code Playgroud)
为什么标准不将std :: unique_ptr 右值的operator *的返回值设为内部值的右值,而不是像这样的lvalue:
// could have been done inside unique_ptr
T& operator*() & { return *ptr; }
T&& operator*() && { return std::move(*ptr); }
Run Code Online (Sandbox Code Playgroud)
在这种情况下,可以正常工作:
std::cout << *std::make_unique<int>(7) << std::endl;
Run Code Online (Sandbox Code Playgroud)
但是开头的代码无法编译(无法将右值绑定到左值)。
旁注:当然,有些人仍然可以像下面这样编写错误的代码,但是更冗长地说“我是UB”,因此不太相关:
auto&& ref = *std::make_unique<int>(7);
std::cout << ref << std::endl;
Run Code Online (Sandbox Code Playgroud)
我最近了解了 r 值引用。为了更彻底的实验,我决定编写一个简单的 DenseMatrix 类。我的问题是是否可以编写任何函数(本例中为 Transpose ),以便auto A = B.Transpose()返回单独的矩阵,但对于auto A = (B + C).Transpose()Transpose 的结果是原位计算的?
今天我大致遇到了以下代码:
\n#include <iostream>\n\nvoid f(float&& f) { std::cout << f << "f "; }\nvoid f(int&& i) { std::cout << i << "i "; }\n\nint main()\n{\n int iv = 2; float fv = 1.0f;\n f(2); f(1.0f);\n f(iv); f(fv);\n}\nRun Code Online (Sandbox Code Playgroud)\n\n正如预期的那样,前两个 f 调用 print 2i 1f。
现在对于第二行,我预计它要么根本不编译,因为 iv 和 fv 不是临时变量(因此不能绑定到 r 值引用),要么它创建要传递给函数的变量的副本,从而打印2i 1f再次打印。
然而,不知何故它打印2f 1i,这几乎是我最没想到的事情。
如果将代码复制到 cppinsights 中,它会将调用转换为
\nf(static_cast<float>(iv));\nf(static_cast<int>(fv));\nRun Code Online (Sandbox Code Playgroud)\n所以它看起来非常有意地将整数转换为浮点数,然后将浮点数转换为整数,但我不知道为什么这样做,也不知道如何谷歌。为什么会出现这种情况?导致这个结果的规则是什么?
\nc++ ×10
rvalue-reference ×10
c++11 ×6
reference ×2
unique-ptr ×2
for-loop ×1
function ×1
multimap ×1
overloading ×1
stdmove ×1
stl ×1