移动构造函数调用返回而不是复制

时间:2017-07-26 20:06:37

标签: c++11 move-semantics

今天我发现这段代码并没有像我希望的那样起作用。 根据我对L值的知识,应该调用复制构造函数,而对于R值,它应该选择移动构造函数。否则std::move的目的是什么,除了强制转换为R值之外什么都不做。我期待return obj将调用复制构造函数,但它调用move。 我知道这里的副本没用,但这是关于规则的。如果我的复制构造函数有副作用并且这是我的情况怎么办(我知道它不应该,但从技术上讲它可以 - 例如:std :: cout call)。 标准中有什么允许这样的行为吗?另外我怎么强制复制?

#include <iostream>

class X
{
public:
    X() = default;

    X(const X& r): i(r.i)
    {
        std::cout << "copy ctor" << std::endl;
    }

    X(const X&& r): i(r.i)
    {
        std::cout << "move ctor" << std::endl;
    }
    int i = 0;
};

X foo()
{
    X obj;
    obj.i = 10;
    return obj;
}

int main()
{
    X x = foo();
}
  

移动ctor

     

移动ctor

1 个答案:

答案 0 :(得分:1)

来自cppreference(强调我的):

  

如果[返回的表达式]是一个左值表达式并且满足或将满足复制省略的条件,除了[返回的表达式]命名一个函数参数,然后重载决策以选择用于初始化的构造函数返回值的执行两次:首先好像[返回的表达式]是一个右值表达式(因此它可以选择移动构造函数或引用const的复制构造函数),如果没有合适的转换是可用的,第二次执行重载决策,使用lvalue [返回表达式](因此它可以选择引用非const的复制构造函数)。   即使函数返回类型与[返回表达式]的类型不同(复制省略需要相同类型),上述规则也适用

长话短说,class ExpandableListViewAdapterDemo extends BaseExpandableListAdapter{ Context context = null; private List<String> headersList;//semester's name and year private HashMap<String, List<String>> tableList;//course names with its grades and gpa static final String TAG = "**Adapter Demo**"; ExpandableListViewAdapterDemo(Context context, List<String> list, HashMap<String, List<String>> hashMap){ this.context = context; headersList = list; tableList = hashMap; Log.e(TAG, "hashmap list value = "+hashMap.get("Spring 2016")); Log.e(TAG, "initial table list value = "+tableList.get("Spring 2016")); printMap(tableList); //printAll(); Log.e(TAG, "groupCount = "+getGroupCount()); } void printAll(){ Log.e(TAG, "headers count = "+headersList.size()); for (int i = 0; i < headersList.size() ; i++) { Log.e(TAG, "header at i="+i+" ,"+headersList.get(i)); } printMap(tableList); } private static void printMap(HashMap mp) { Iterator it = mp.entrySet().iterator(); while (it.hasNext()) { HashMap.Entry pair = (HashMap.Entry)it.next(); Log.e(TAG, "#253 : "+pair.getKey() + " = " + pair.getValue()); it.remove(); // avoids a ConcurrentModificationException } } @Override public int getGroupCount() { Log.e(TAG, "#299 : table list value = "+tableList.get("Spring 2016")); return headersList.size(); } @Override public int getChildrenCount(int i) { //Log.e(TAG, "at i="+i+" "+headersList.get(i)); int returns = 0; Log.e(TAG, "#307 : table list value = "+tableList.get("Spring 2016")); if (tableList.get(headersList.get(i)) != null) returns = tableList.get(headersList.get(i)).size(); else Log.e(TAG, "tableList is null"); Log.e(TAG, "details size = "+returns); Log.e(TAG, "group count = "+getGroupCount()); int tosubtract = 2 * getGroupCount(); if (returns>tosubtract) returns = returns - tosubtract - 2; Log.e(TAG, "child count returns = "+String.valueOf(returns) ); return i; } @Override public Object getGroup(int i) { Log.e(TAG, "#323 : table list value = "+tableList.get("Spring 2016")); return headersList.get(i); } @Override public Object getChild(int i, int i1) { Log.e(TAG, "#329 : table list value = "+tableList.get("Spring 2016")); return tableList.get(headersList.get(i)).get(i1); } @Override public long getGroupId(int i) { Log.e(TAG, "#335 : table list value = "+tableList.get("Spring 2016")); return i; } @Override public long getChildId(int i, int i1) { Log.e(TAG, "#340 : table list value = "+tableList.get("Spring 2016")); return i1; } @Override public boolean hasStableIds() { Log.e(TAG, "#347 : table list value = "+tableList.get("Spring 2016")); return false; } @Override public View getGroupView(int i, boolean b, View view, ViewGroup viewGroup) { Log.e(TAG, "#353 : table list value = "+tableList.get("Spring 2016")); String semesterTitle = (String) getGroup(i); if (view == null){ LayoutInflater inf = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); view = inf.inflate(R.layout.previous_semesters_result_list_headers, null); } TextView semesterName = (TextView) view.findViewById(R.id.semester_name); semesterName.setText(semesterTitle); return view; } @Override public View getChildView(int i, int i1, boolean b, View view, ViewGroup viewGroup) { Log.e(TAG, "#367 : table list value = "+tableList.get("Spring 2016")); String courseIdTitle = (String) getChild(i, i1); String gpa = (String) getChild(i, i1+getChildrenCount(i));//previously i1+4 String grade = (String) getChild(i, i1+getChildrenCount(i)+getChildrenCount(i)); if (view == null){ LayoutInflater inf = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); view = inf.inflate(R.layout.previous_semesters_results_list_child, null); } TextView courseIdValue = (TextView) view.findViewById(R.id.course_id_column_value); courseIdValue.setText(courseIdTitle); TextView gradeValue = (TextView) view.findViewById(R.id.grade_column_value); gradeValue.setText(grade); TextView gpaValue = (TextView) view.findViewById(R.id.gpa_column_value); gpaValue.setText(gpa); return view; } @Override public boolean isChildSelectable(int i, int i1) { Log.e(TAG, "#386 : table list value = "+tableList.get("Spring 2016")); return true; } } 隐含地试图在有意义的时候移动你返回的东西。它只会作为最后的手段复制(例如,没有移动构造函数)。