以下代码
#include <vector>
#include <string>
#include <iostream>
std::string const& at(std::vector<std::string> const& n, int i)
{
return n[i];
}
std::vector<std::string> mkvec()
{
std::vector<std::string> n;
n.push_back("kagami");
n.push_back("misao");
return n;
}
int main()
{
std::string const& s = at(mkvec(), 0);
std::cout << s << std::endl; // D'oh!
return 0;
}
Run Code Online (Sandbox Code Playgroud)
可能导致崩溃,因为原始矢量已经在那里被破坏.在引入rvalue-reference之后的C++ 2011(c ++ 0x)中,如果vector参数是rvalue ,则可以使用已删除的函数声明来完全禁止调用at
std::string const& at(std::vector<std::string>&&, int) = delete;
Run Code Online (Sandbox Code Playgroud)
这看起来不错,但以下代码仍会导致崩溃
int main()
{
std::string const& s = mkvec()[0];
std::cout << s << std::endl; // D'oh!
return 0;
} …Run Code Online (Sandbox Code Playgroud) 如果我有一个实现移动语义的类:
class BigObject
{
public:
BigObject(something x = something()) { ... }
BigObject(const BigObject& other) { ... }
BigObject(BigObject&& other) { ... }
BigObject& operator=(BigObject other) { ... }
void swap(BigObject& other) { ... }
// [...]
};
auto begin = std::begin(somethingSequence); // collection doesn't matter here
auto end = std::end(somethingSequence); // collection doesn't matter here
BigObjectOutputIterator dest; // collection doesn't matter here
Run Code Online (Sandbox Code Playgroud)
在lambda中返回BigObject的正确方法是什么?
std::transform(begin, end, dest,
[](something x) -> BigObject {return BigObject(x); });
Run Code Online (Sandbox Code Playgroud)
要么
std::transform(begin, end, dest,
[](something x) …Run Code Online (Sandbox Code Playgroud) 以下示例代码编译.
#define USE_RVALUE // line 1
template<class data_type>
class Container
{
data_type& data;
public:
#ifdef USE_RVALUE
Container(data_type&& _data) : data(_data) {}
#endif
Container(data_type& _data) : data(_data) {}
};
int main()
{
double d = 42.0;
Container<double> c1(d);
Container<double> c2(1.0f); // line 18
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我的编译命令:
g++ -std=c++11 -Wall ref.cpp -o ref # g++ is 4.7.1
Run Code Online (Sandbox Code Playgroud)
如果我们退出第1行,g ++会抱怨:
no matching function for call to ‘Container<double>::Container(float)’
ref.cpp:18:34: note: candidates are:
ref.cpp:11:9: note: Container<data_type>::Container(data_type&) [with data_type = double]
ref.cpp:11:9: note: no known …Run Code Online (Sandbox Code Playgroud) 我试图编译:
int &&a=3;
int &b=a;
Run Code Online (Sandbox Code Playgroud)
它的工作原理.我知道"a"是一个左值,但为什么我可以将"rvalue to int"绑定到"对int的lvalue引用(而不是对int的rvalue引用)"?这样,我可以改变临时值,3:
b=5 //changing the value of the temporary bound to the rvalue reference
Run Code Online (Sandbox Code Playgroud)
这个tecnique用于std :: forward,所以我认为这是一个标准的行为.对int的rvalue引用是否被视为存储临时的简单int左值?如果没有,你如何解释绑定?
我不确定这是否是我的C++语法错误,或者这是否是根本无法完成的事情.
我想定义一个将std :: map作为构造函数参数的类.然后我想通过传递一个"临时"(适当调用这个"rvalue"?)std :: map来创建该类的实例.即我不想创建一个左值std :: map,然后将其传递给构造函数.
这可以实现吗?我尝试了以下(注释行显示失败的尝试)
#include <map>
#include <string>
#include <iostream>
class Test
{
public:
Test(std::map<int,char>& rMap)
{
std::map<int,char>::iterator iter;
for (iter = rMap.begin(); iter != rMap.end(); ++iter)
{
mMap[iter->first] = mMap[iter->second];
}
}
virtual ~Test(){}
protected:
std::map<int, char> mMap;
};
int main()
{
std::cout << "Hello world!" << std::endl;
//Test test({1,'a'}); // Compile error.
//Test test(std::map<int,char>(1,'a')); // Also compile error.
//Test test(std::map<int,char>{1,'a'}); // Yet again compile error.
return 0;
}
Run Code Online (Sandbox Code Playgroud)
这是我的编译器:
g++ (GCC) 4.4.7 20120313 …Run Code Online (Sandbox Code Playgroud) 当我研究右值参考时,我从stackoverflow中找到了一个奇怪的答案.
提问者希望避免在接收参数作为左值引用的函数与另一个接收右值引用的函数之间的代码重复.这两个函数都做同样的事情.
这是问题: -
void foo(X& x) { /*complex thing*/ } //#A
void foo(X&& x) { /*complex SAME thing*/ } //#B
Run Code Online (Sandbox Code Playgroud)
这是建议的解决方案.它被我修改了一下: -
void foo(X& x) { /*complex thing*/ } //#A
void foo(X&& x) { foo(x); } //#B
Run Code Online (Sandbox Code Playgroud)
为什么这不会导致堆栈溢出异常?
为什么foo#B打电话foo#A,但不是foo#B?
更具体地说,哪个C++规则强制执行此行为?
可以说我们有以下课程:
class Foo
{
public:
Foo() { _bar=new Bar };
Foo(const Foo &right) { _bar=new Bar(right.bar); };
Foo(Foo &&right) { _bar=right._bar; right.bar=new Bar(); };
~Foo() { delete _bar; }
Foo &operator=(const Foo &right) { _bar->opertor=(right.bar); return *this;}
Foo &operator=(Foo &&right) { std::swap(_bar, right._bar); return *this;}
void func() { _bar->test=1 };
private:
Bar *_bar;
};
Run Code Online (Sandbox Code Playgroud)
将它更改为以下内容是否合法并期望最终用户知道在执行移动后rvalue不再有效(在调用除了赋值运算符之外的任何其他内容可能会崩溃)?
class Foo
{
public:
Foo() { _bar=new Bar };
Foo(const Foo &right) { _bar=new Bar(right.bar); };
Foo(Foo &&right) { _bar=right._bar; right.bar=nullptr; };
~Foo() { if(_bar …Run Code Online (Sandbox Code Playgroud) 这主要是关于与固定大小的数组相关的C++语法的一个问题.
假设我有一个利用类型信息的函数,例如:
template<class T> void fun(T const& t){
std::cout << typeid(t).name() << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
我可以传递一个值或一个临时对象:
int i;
fun(i); // prints "int" ("i" actually)
fun(int{}); // prints "int" ("i" actually)
Run Code Online (Sandbox Code Playgroud)
但是我不能对数组做同样的事情
double a[10][10];
fun(a); // ok, prints "a[10][10]" ("A10_A10_d" actually)
fun(double[10][10]); // doesn't compile
fun(double{}[10][10]); // doesn't compile
fun(double[10][10]{}); // doesn't compile
fun(double()[10][10]); // doesn't compile
fun(double[10][10]()); // doesn't compile
fun(double(&)[10][10]); // doesn't compile
fun(double(*)[10][10]); // doesn't compile
Run Code Online (Sandbox Code Playgroud)
我原则上可以这样做:
typedef double a1010[10][10];
fun(a1010{});
Run Code Online (Sandbox Code Playgroud)
但是,有没有预先定义一个typedef呢?
是否有可能将一个固定大小的数组作为函数参数就地构造?
完整代码:
template<class T> void fun(T …Run Code Online (Sandbox Code Playgroud) 假设您已将2 vectors传递给函数lvalue references。后来您意识到,可以使用递归并vectors使用它们的切片iterators。
难道是一个恰当的策略,如果我继续前进,写一些util功能,利用这些vecotrs作为rvalues?还是我应该以任何方式避免这种情况?
简化模式:
Node* util(vector<int>&& a, vector<int>&& b) {
Node* root = new Node(a[0]);
root->left = util({ a.begin(), a.end() }, { b.begin(), b.end() });
root->right = util({ a.begin(), a.end() }, { b.begin(), b.end() });
return root;
}
Node* main(vector<int>& a, vector<int>& b) {
return util({ a.begin(), a.end() }, { b.begin(), b.end() });
}
Run Code Online (Sandbox Code Playgroud)
实际示例(LeetCode 105):
TreeNode* util(vector<int>&& preorder, vector<int>&& inorder) {
if …Run Code Online (Sandbox Code Playgroud) 由于遗留原因,const char*我正在处理的代码中有很多用法。我试图限制这一点,偶然发现了我想知道的东西。我有类似的东西:
class AClass {
public:
const char* getValue() { return _value.c_str(); }
private:
std::string _value;
}
Run Code Online (Sandbox Code Playgroud)
但是,此类现在可以通过副本返回,例如。按功能:
AClass getAClass();
Run Code Online (Sandbox Code Playgroud)
我们也可能想将其传递给这样的东西:
void functionFromOtherLibrary(const char* value);
Run Code Online (Sandbox Code Playgroud)
现在考虑一下,这可能会导致错误:
functionFromOtherLibrary(getAClass().getValue());
Run Code Online (Sandbox Code Playgroud)
因为该中间体有资格在那时被销毁。即使上面的方法没问题,因为这只是一个陈述,所以这可能不会:
const char* str = getAClass().getValue();
functionFromOtherLibrary(str);
Run Code Online (Sandbox Code Playgroud)
所以我在想写一些类似的东西:
class AClass {
public:
const char* getValue() { return _value.c_str(); }
const char* getValue() && = delete;
}
Run Code Online (Sandbox Code Playgroud)
禁止在右值上调用该方法。只是尝试给了我:
error C2560: cannot overload a member function with ref-qualifier with a member function without ref-qualifier
Run Code Online (Sandbox Code Playgroud)
我不确定这是否:
const char*s 的代码,它似乎总是依赖于这样一个事实,即返回值的对象仍然存在并保存源代码std::string。 …